如何将双指针从 C++ dll 返回到 C#

本文关键字:dll 返回 C++ 指针 | 更新日期: 2023-09-27 18:36:51

我正在尝试从我的C++ dll返回指向C#的指针。我尝试了所有方法,但我的双精度指针没有值。

以下是我对C++ dll的导入:

[DllImport("/Resources/libfli.dll", EntryPoint = "FLIGetTemperature")]
public static extern unsafe int FLIGetTemperature(long dev, double* temperature);
// Get the temperature of a given camera. This function places the temperature of the CCD camera 
// cold finger of device dev in the location pointed to by temperature.
// Return Value: Zero on success. Non-zero on failure.
// Parameters: dev Camera device to get the temperature of.
// temperature Pointer to where the temperature will be placed.
// See Also: FLISetTemperature

FliGetTemperatre的定义来自FLI_SDK_Documentation

LIBFLIAPI FLIGetTemperature (flidev_t dev, double* temperature)
Get the temperature of a given camera.

以下是我向 .C# 中的 Dll:

unsafe public void GetTheTemperatureOfTheCamera()
{
    int success=0;
    long ldev = 0;
    long* dev = &ldev;
    double lTemperature = 0;
    double* temperature = &lTemperature;
    success = FLIGetTemperature(ldev, temperature);
}

当我运行代码时,出现以下错误:

myApplication 中发生了类型为"System.AccessViolationException"的未处理异常.exe

其它信息:尝试读取或写入受保护的内存。这通常表示其他内存已损坏。

我也尝试了封送和IntPtr,但这也不起作用。

我已经尝试过 Fliopen 该功能有效。它成功了。下面是FliOpen的代码。

    [DllImport("/Resources/libfli.dll", EntryPoint = "FLIOpen")]
    public static extern unsafe int FLIOpen(long* dev, string name, long domain);
    unsafe public int InitDevice()
    {
        long ldev = 0;
        long* dev = &ldev;
        int success;
        string deviceName = "flipro0";// this is default name for device
        long domainName = 258; //this is default domain name
        success = FLIOpen(dev, deviceName, domainName);
        return success;
    }

FLIOpen方法虽然是成功的

如何将双指针从 C++ dll 返回到 C#

阅读文档,我会写这样的东西:

unsafe public void GetTheTemperatureOfTheCamera()
{
     int success=0;
     long dev = 0;
     long* ldev  = &dev;
     success = FLIOpen(ldev, deviceName, domainName); //Get the device handle.
     if (success != 0)
        throw new Exception("Cannot open device");
     double lTemperature = 0;
     double* temperature = &lTemperature;
     success = FLIGetTemperature(dev, temperature);
}

C# long参数与非托管类型flidev_t不匹配。关键是long是 64 位类型。假设你的代码在Windows中运行,那么flidev_t,它是C++ long的别名,是32位宽。

您也不需要此处的不安全代码。您可以像这样声明函数:

[DllImport("/Resources/libfli.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int FLIGetTemperature(int dev, out double temperature);

我还假设调用约定是cdecl,但您可能需要检查C++头文件以确保这一点。

您需要在其他 p/invoke 声明中进行其他更改。基本上,在将flidev_t转换为 C# long的任何地方都应将其更改为 int 。甚至可能是IntPtr.然后,您将比非托管代码领先一步,我怀疑该代码目前不适合64位端口!

FLIOpen开始,这将是:

[DllImport("/Resources/libfli.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int FLIOpen(out int dev, string name, int domain);

好吧,域参数可能更好地转换为具有int基类型的 C# 枚举。