10

I need to use a library of C functions in a DLL from a C# application. I am having trouble calling DLL functions with char * arguments:

The C DLL:

extern "C" __declspec(dllexport) int CopyFunc(char *, char *);
int CopyFunc(char *dest, char *src)
{
    strcpy(dest, src);
    return(strlen(src));
}

the C# app needs to look something like this:

[DllImport("dork.dll")]
public static extern int CopyFunc(string dst, string src);

int GetFuncVal(string source, string dest)
{
    return(CopyFunc(dest,source));
}

I've seen examples using string or StringBuilder, or IntPtr as replacements for the char * required by the DLL function prototype, but I've not been able to get any of them to work. The most common exception I get is that PInvoke is unbalancing the stack because the function call does not match the prototype.

Is there a simple solution to this?

1
  • 2
    A char * is a pointer to a 1-byte character type. A C# string is Unicode. You need to straighten that out first. Commented Oct 11, 2016 at 22:02

1 Answer 1

10

Update your P/Invoke declaration of your external function as such:

[DllImport("dork.dll")]
public static extern int CopyFunc([MarshalAs( UnmanagedType.LPStr )]string a, [MarshalAs( UnmanagedType.LPStr )] string b);

int GetFuncVal(string src, string dest)
{
    return(CopyFunc(dest,src));
}
Sign up to request clarification or add additional context in comments.

3 Comments

That did work; however the DLL function modifies one of the char * parameters; the string 'dest' in the caller remains unmodified. How do I get this change to return to the C# caller? Most of the functions in the DLL modify passed buffers. What I will actually need to do is create a byte array with binary data, pass it to the DLL expecting a char *, and receive the modified byte array back from the DLL.
Try adding out keyword to the string dest public static extern int CopyFunc([MarshalAs( UnmanagedType.LPStr )]string a, [MarshalAs( UnmanagedType.LPStr )] out string b); or public static extern int CopyFunc([MarshalAs( UnmanagedType.LPStr )]string a, [Out, MarshalAs( UnmanagedType.LPStr )] string b);
Thanks for your answer! I ended up tinkering with this and got it all to work by using byte arrays instead of strings. I also had to change the UnmanagedType to LPArray. Now I have the bidirectional arrays functioning as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.