开发者

Tried to call an unmanaged DLL, but it always returns junk values. Please help!

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.

Unmanaged Codes:


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");
}

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[] arrayOfStr开发者_运维知识库uct = new ManagedStruct[3];
string message;

//Assign values to arrayOfStruct

//Call interop
Process(arrayOfStruct, 3, message);


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);

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();

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜