4

I have a C++ dll that I need to call from C#. One of the functions in the dll requires a char* for an input parameter, and another function uses a char* as an output parameter.

What is the proper way to call these from C#?

5 Answers 5

3

string should work if the parameter is read-only, if the method modifies the string you should use StringBuilder instead.

Example from reference below:

 [DllImport ("libc.so")]
 private static extern void strncpy (StringBuilder dest, 
      string src, uint n);

 private static void UseStrncpy ()
 {
    StringBuilder sb = new StringBuilder (256);
    strncpy (sb, "this is the source string", sb.Capacity);
    Console.WriteLine (sb.ToString());
 }

If you don't know how p/invoke marshaling works you could read http://www.mono-project.com/Interop_with_Native_Libraries

If you are only conserning with strings, read only the section: http://www.mono-project.com/Interop_with_Native_Libraries#Strings

Sign up to request clarification or add additional context in comments.

Comments

2

Just using strings will work fine for input parameters, though you can control details about the string with the MarshalAs attribute. E.g.

[DllImport("somedll.dll", CharSet = CharSet.Unicode)]
static extern void Func([MarshalAs(UnmanagedType.LPWStr)] string wideString);

As for returning char* parameters, that's a little more complex since object ownership is involved. If you can change the C++ DLL you can use CoTaskMemAllocate, with something like:

void OutputString(char*& output)
{
    char* toCopy = "hello...";
    size_t bufferSize = strlen(toCopy);
    LPVOID mem = CoTaskMemAlloc(bufferSize);
    memcpy(mem, toCopy, bufferSize);
    output = static_cast<char*>(mem);
}

The C# side then just uses an 'out string' parameter, and the garbage collector can pick up the ownership of the string.

Another way of doing it would be to use a StringBuilder, but then you need to know how big the string will be before you actually call the function.

Comments

0

Not sure this works, but have you tried with

StringObject.ToCharArray();

Not sure about initialising the String from char * tho. Mybe just assign to a string object, its worth a try.

Comments

0

Have you tried StringBuilder? I found this in a Google search:

[DllImport("advapi32.dll")]
public static extern bool GetUserName(StringBuilder lpBuffer, ref int nSize);

If you post the call you're making we can help you assemble it.

Comments

0

If the DLL function is expecting an allocated buffer of char* (not a wide/multibyte buffer) then the following will work:

[DllImport("somedll.dll", CharSet = CharSet.Ansi)]
static extern void TheFunc(byte[] someBuffer, int someSize);

Here a buffer allocated in c# is passed to TheFunc which fills it with a string of characters (of type char). Bytes aren't "interpreted" by C# they are treated like 8 bit integers, so are perfect for holding 8 bit characters.

An example code snipped would therefore be:

byte[] mybuffer;
int bufSize;

bufSize = 2048;
mybuffer = new byte[bufSize];

TheFunc(mybuffer, bufSize);

string value;
for(value = "", int ix  = 0; (mybuffer[ix] != 0) && (ix < bufSize); ix++)
  value += (char) mybuffer[ix];

DoSomethingWithTheReturnedString(value);

Comments

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.