试图调用非托管DLL,但它总是返回垃圾值.请帮忙! [英] Tried to call an unmanaged DLL, but it always returns junk values. Please help!
问题描述
有人可以帮助我找出以下代码段的错误之处.我试图调用一个旧的DLL,花了大约3天的时间,但是找不到为什么我返回的数组和字符串总是垃圾.
Could someone please help me figure out what is wrong with the following code snippet. I tried to call an old DLL and have spent about 3 days but couldn't find why my returned array and the string is always junk.
非托管代码:
typedef struct
{
double a;
double b;
}UnmanagedStruct, far *lpUnmagedStruct;
//.h file:
__declspec( dllexport ) double far pascal Process(lpUnmagedStruct lpStruct, int size, char far szMessage[]);
//.cpp
extern double far pascal Process(lpUnmagedStruct lpStruct, int size, char far szMessage[])
{
//Please pay attention here. It's being seen as a pointer to an array
lpStruct[0] = ...
lpStruct[2] = ...
_fstrcpy (szMsg, "Welcome");
}
这是我在.NET中的代码:
And here's my codes in the .NET:
[StructLayout(LayoutKind.Sequential)]
public struct ManagedStruct
{
public double a;
public double b;
}
[DllImport("MyDll.dll", EntryPoint="Process", CharSet = CharSet.Ansi)]
public static extern double Process([In, Out]ManagedStruct[] myStruct, int size, string message);
//Implementation
ManagedStruct[] arrayOfStruct = new ManagedStruct[3];
string message;
//Assign values to arrayOfStruct
//Call interop
Process(arrayOfStruct, 3, message);
推荐答案
pascal 调用约定是您的问题.它很古老,pinvoke编组不支持它.它从左到右传递参数,pinvoke marshaller假定使用stdcall,因此从右到左传递参数.使用__stdcall代替:
The pascal calling convention is your problem. It is ancient, the pinvoke marshaller doesn't support it. It passes arguments left-to-right, the pinvoke marshaller is assuming stdcall so passes them right-to-left. Use __stdcall instead:
__declspec( dllexport )
double __stdcall Process(lpUnmagedStruct lpStruct, int size, char* szMessage, int messageSize);
下一个问题是字符串,返回一个字符串需要您在声明中使用StringBuilder并在调用中传递一个已初始化的字符串:
Next problem is the string, returning one requires you to use a StringBuilder in the declaration and pass an initialized one in the call:
[DllImport("MyDll.dll", EntryPoint="Process", CharSet = CharSet.Ansi)]
public static extern double Process(ManagedStruct[] myStruct, int size, StringBuilder message, int messageSize);
...
var buffer = new StringBuilder(666);
double retval = Process(arrayOfStruct, 3, buffer, buffer.Capacity);
var message = buffer.ToString();
我随意添加了messageSize参数,这是将字符串安全地复制到消息缓冲区中而又不破坏销毁垃圾收集堆的风险所必需的.
I took the liberty of adding the messageSize argument, required to safely copy the string into the message buffer without risking destroying the garbage collected heap.
这篇关于试图调用非托管DLL,但它总是返回垃圾值.请帮忙!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!