-1

What I am trying to achieve: I am trying to access a C++ application's functions through its DLL in a C# (Interop).

Issue which I am facing right now: When i create a std::string return type function in C++ and calls it through its DLL in C# code there is now output at all.

Code which I have written for C++ APP

extern "C"

{

    __declspec(dllexport) int SM_Interop_API_Add(int a, int b)
    {
        return a + b;
    }

    __declspec(dllexport) std::string SM_Interop_API_getLanguage()
    {
        return "This is Test String";
        //return getLanguage();
    }
}

Code which I have written for C# APP

    class Program
    {
        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi,EntryPoint = "SM_Interop_API_Add")]
        public static extern int SM_Interop_API_Add(int a, int b);

        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "SM_Interop_API_getLanguage")]
        public static extern string SM_Interop_API_getLanguage();

        static void Main(string[] args)
        {

            Console.WriteLine("Hello World!");
            int sum = SM_Interop_API_Add(10, 10);
            Console.WriteLine($"Result: {sum}");
            string result = SM_Interop_API_getLanguage();
            Console.WriteLine($"Sm Language: {result}");
            Console.WriteLine("----EOP----");


        }
    }

In the above code for C++, SM_Interop_API_getLanguage is supposed to return a string, and when I calls it through its DLL in C# code it does not return any result at all, first, I tried by returning the actual output of getLanguage which did not work then I tried to return some hard codded string but that is also coming as output. Also to mention the function with int return type works perfectly only std::string return type is not working here in my case.

Kindly guide me if I am doing anything wrong or missing anything. Any help is appreciated.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Shivam
  • 3
  • 1

1 Answers1

0

std::string will never work here as the marshaller does not know how to free it.

Instead, you need to pass in a buffer from the C# side, like this

    class Program
    {
        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi,EntryPoint = "SM_Interop_API_Add")]
        public static extern int SM_Interop_API_Add(int a, int b);

        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "SM_Interop_API_getLanguage")]
        public static extern void SM_Interop_API_getLanguage(StringBuilder buffer)

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            int sum = SM_Interop_API_Add(10, 10);
            Console.WriteLine($"Result: {sum}");
            var result = new StringBuilder(200);
            SM_Interop_API_getLanguage(result);
            Console.WriteLine($"Sm Language: {result}");
            Console.WriteLine("----EOP----");
        }
    }

Then on the C++ side, you simply copy it in (not great with C++, guessing a bit)

    __declspec(dllexport) void SM_Interop_API_getLanguage(char* buffer)
    {
        strcpy(buffer, "This is Test String");
        //return getLanguage();
    }

Passing a buffer size and checking that it's large enough would be wise also.

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • with this approach, I get a new error, Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. – Shivam Aug 19 '21 at 05:47