简体   繁体   中英

Marshalling C++ .dll in C#

I am developing a C# application that uses a dll written in C++. I am able to call most of the functions in .dll from C# application, but only one function cause problem. I think it is about marshalling types.

This is the C++ prototype of the function:

int GetProgressInfo(
    int *state, 
    double *progress, 
    char* stateInfo, 
    int infoStringMaxLen
);

This is my C# delegate:

delegate int GET_PROGRESS_INFO(
    ref int state, 
    ref double progress, 
    [MarshalAs(UnmanagedType.LPStr)] 
    string stateInfo, 
    int infoStringMaxLen
);

Can you please help me? I can not find what is wrong

One very important lesson that you must learn is that the signature of a function is not enough information to fully specify the semantics for that function. In this case, a C++ int* could be the address of a single int , or an array. Likewise for double* . And char* could be a string being passed to the function, or a pointer to a buffer in which the function returns a string to the caller.

I'm going to take my best guess, but you do need to check the actual semantics.

My best guess is that the function returns three things to the caller: an int with the state int, a double with the progress value, and a string giving info on the state. The latter information is encoded in the final two parameters. The caller allocates a buffer and passes the pointer to the beginning, together with the length. So the C# should look like this:

delegate int GET_PROGRESS_INFO(
    out int state, 
    out double progress, 
    StringBuilder stateInfo, 
    int infoStringMaxLen
);

I'm assuming that you are using the default charset of CharSet.Ansi , and so the third parameter does not need a MarshalAs attribute.

Call the function like this:

int state;
double progress;
StringBuilder stateInfoSb = new StringBuilder(256);
int retval = GetProgressInfo(
    out state, 
    out progress, 
    stateInfoSb, 
    stateInfoSb.Capacity
);
if (retval == 0) // guessing that 0 means OK
{
    string stateInfo = stateInfoSb.ToString();
    ....
}

Another possible cause for mismatch is the calling convention. As written, there are no calling conventions specified. The default for C++ code is cdecl, the default for C# is stdcall. You need to check what calling convention is used by the C++ and make sure the C# code matches.

And once again, you do need to check with the documentation that my guesswork above is accurate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM