Search code examples
c#c++dllexport

Create C++ dll with functions whose arguments can be called as out parameter in c#


I want to create a function in c++ that takes two parameter(char[], int) and modifies the parameters(Similar to out parameter in c#) and then create a dll that can be used in c#.

C++ Sample Code:

static void funct(char * name, int size)
{
    char[] testName="John";
    name=&testName;
    size=5;
}

C# Sample Code:

  const string dllLocation = "D:\\Test.dll";
  [DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
  private static extern void funct(StringBuilder name, int size);

This is not correct code. It is just to give an idea of what I want. I want to use c# to access the c++ function through dll and obtain the name and size(no of characters).


Solution

  • Use pointers in the C++ side and marshal these by ref on the C# side.

    static void funct(char** name, int* size)
    {
        char[] testName="John";
        *name=&testName;
        *size=5;
    }
    
    const string dllLocation = "D:\\Test.dll";
    [DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
    private static extern void funct(ref StringBuilder name, ref int size);
    

    Beware with the char array, it may create memory leaks or worse crashes, it would be better to first test the size of the buffer and the size of the data you want to pass to C#, if there is enough room copy it, else inform to C# that it needs more size so it's allocated by C#.

    Something like this:

    static int funct(char** name, int* size, int bufferSize)
    {
        if(bufferSize < 4)
            return 4;
    
        char[] testName="John";
        memcpy(name*, &char[0], 4);
        *size=5;
        return -1;
    }
    
    
    const string dllLocation = "D:\\Test.dll";
    [DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
    private static extern void funct(ref StringBuilder name, ref int size, int bufferSize);
    
    StringBuilder sb = null;
    int size = 0;
    
    //Request size
    int neededSize = funct(ref sb, ref size, 0);
    //Create buffer with appropiate size
    sb = new StringBuilder(neededSize);
    //Call with the correct size, test result.
    if(funct(ref sb, ref size, neededSize) != -1)
        throw new Exception();