正确使用DllImport

ins*_*pid 7 c# dll pinvoke unmanaged marshalling

假设int NativeMethod(double, double *)Native.dll中有一个c ++方法.我第一次尝试从托管代码调用此方法是(假设我不需要指定入口点)

[DllImport("Native.dll")]
private static extern int NativeMethod(double inD, IntPtr outD);
Run Code Online (Sandbox Code Playgroud)

然后使用我做的DLL

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
NativeMethod(2.0, x);

//do stuff with x

Marshal.FreeHGlobal(x);  //crash
Run Code Online (Sandbox Code Playgroud)

我想知道为什么会在这里崩溃.我的第一个猜测是,由于DLL和我的应用程序可能使用不同的CRT这是一个堆问题.但如果是这样的话,为什么不会对NativeMethod的调用崩溃呢?该方法返回一个x,我可以成功地从中提取双精度.

我可以通过引用传递double来使导入工作

[DllImport("Native.dll")]
private static extern int NativeMethod(double inD, IntPtr outD);
Run Code Online (Sandbox Code Playgroud)

为什么FreeHGlobal在第一次尝试时崩溃,以及将指针传递给本机方法的推荐方法是什么?out关键字可能在这种情况下正常工作,但如果我需要Marshal一个字符串怎么办?我认为我无法绕过AllocH和FreeH ......

Mar*_*ins 7

我可能误解了你的目标,但似乎你让它变得比必要的更复杂.只需通过引用传递它,让下面的编组处理它.

[DllImport("Native.dll")]
private static extern int NativeMethod(double inD, ref double outD);

double x;

x = 1;
NativeMethod( 2.0, ref x );
Run Code Online (Sandbox Code Playgroud)


Jar*_*Par 5

问题是该方法采用的double*是指向double的指针.你正在传入指向一个指针IntPtr.这一点很重要,因为double(8字节)和IntPtr可变大小(4或8字节)之间存在大小差异.您需要将指针分配给adouble

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double));
Run Code Online (Sandbox Code Playgroud)