2

I have a large library written in C that I would like to use as a DLL in a C# program. Most of the C code will be used by the libraries own functions, but I do need one function to be able to be called from the C# project.

So there's an example C function below

__declspec(dllexport) char* test(char* a){
    char* b = "World";
    char* result = malloc(strlen(a) + strlen(b) + 1);

    strcpy(result, a);
    strcpy(result, b);

    return result;
}

Now in the C# code I have got using System.Running.InteropServices; and also [DllImport("mydll.dll")] but I'm not sure how to declared the function.

public static extern char* test(char* a); obviously doesn't work because C# doesn't support pointers like C does.

So how should I pass a string to this C function and have it return a string as well?

9
  • do you have to use the C library why can't you write your own method to handle the same thing in C# this seems pretty straight forward in my opinion.. Commented Oct 17, 2016 at 15:19
  • 1
    C# does support pointers, just like C, but you don't need them here. Your function returns an int but you're trying to return a char* - that's an error. And usually you provide the function a buffer for it to fill, or you'll have to export a second function just to free the string you allocated. Commented Oct 17, 2016 at 15:22
  • Returning a string like this is a leak. See stackoverflow.com/questions/5298268/… for the proper way to do it. Commented Oct 17, 2016 at 15:23
  • @MethodMan This was just an example. The real C code is a lot more in depth. Commented Oct 17, 2016 at 15:25
  • 1
    The argument is simply string. The return value is a problem however, the pinvoke marshaller is going to try to release the string buffer with CoTaskMemFree() and that is not going work. Beware that this function is also hard to call reliably from a C program. You need to expose another helper function that calls free(). Declare as IntPtr in C# and use Marshal.PtrToStringAnsi(). A much smarter signature is int test(const char* a, char* buffer, int buflen), allow you declare the 2nd argument as StringBuilder and return an error code when buflen isn't big enough. Commented Oct 17, 2016 at 15:25

1 Answer 1

9

You're looking for a MarshalAs attribute:

   [DllImport("mydll.dll")]
   static public int test([MarshalAs(UnmanagedType.LPStr)]String a);

As for returning a dynamically allocated C string, bad idea. How will you reliably de-allocate the string? It's a recipe for a memory leak. Allocate a byte array in C#, pin it and pass it to the C code along with its size so the C code can copy the result into it. Then convert to a string using System.Text.Encoding.ASCII.GetString().

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

1 Comment

Yes, except OP's function is broken (see my comment on the question)

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.