Return string from c++ dll export function called from c#

前端 未结 4 2010
灰色年华
灰色年华 2021-02-09 16:37

I am trying to return a string from a c++ dll export function. I am calling this function from c#. I have seen a lot of examples on the internet and I am really confused what to

相关标签:
4条回答
  • 2021-02-09 16:58

    How about this (Note, it assumes correct lengths - you should pass in the buffer length and prevent overflows, etc):

    extern "C" __declspec(dllexport)  void  __cdecl getDataFromTable(char* tableName, char* buf)
    {
        std::string st = getDataTableWise(statementObject, columnIndex);
        printf(st.c_str()); 
    
        strcpy(buf, st.c_str());
    } 
    

    Then in C#:

    [DllImport("\\SD Card\\ISAPI1.dll")]
    private static extern string getDataFromTable(byte[] tablename, byte[] buf);
    static void Main(string[] args)
    {
        byte[] buf = new byte[300];
        getDataFromTable(byteArray, buf);
        Console.writeLine(System.Text.Encoding.ASCII.GetString(buf));
    }
    

    Note, this does make some assumptions about character encodings in your C++ app being NOT unicode. If they are unicode, use UTF16 instead of ASCII.

    0 讨论(0)
  • 2021-02-09 17:22

    On windows you can return string directly using BSTR (from wtypes.hincluded by windows.h). BSTRcan be created from standard wide string bySysAllocString function:

    _declspec(dllexport) BSTR getDataFromTable(const char* tableName)
    {
        return SysAllocString(L"String to return");
    }
    

    Then in C# you marshal the return type as BStr:

    [DllImport("\\SD Card\\ISAPI1.dll", CallingConvention = CallingConvention.Cdecl )]
    [return: MarshalAs(UnmanagedType.BStr)]
    static extern string getDataFromTable(string tableName);
    
    0 讨论(0)
  • 2021-02-09 17:25

    I have had this problem too, recently, and though I have a solution for you, sadly I can't really explain it. I haven't found a sound explanation yet.

    my c++ code for retrieving a string is:

    extern "C" { __declspec(dllexport) void __GetValue__(char* str, int strlen); }
    

    and my C# code:

    [DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void __GetValue__(StringBuilder str, int strlen);
    

    So as you can see, instead of returning a value, you can supply a string (by using StringBuilder) and let C++ fill in the data like:

    void __GetValue__(char* str, int strlen) {
        std::string result = "Result";
    
        result = result.substr(0, strlen);
    
        std::copy(result.begin(), result.end(), str);
        str[std::min(strlen-1, (int)result.size())] = 0;
    }
    

    And for completeness the C# code to request the string:

    public String GetValue() {
        StringBuilder str = new StringBuilder(STRING_MAX_LENGTH);
    
        __GetValue__(str, STRING_MAX_LENGTH);
    
        return str.ToString();
    }
    
    0 讨论(0)
  • 2021-02-09 17:26

    The .NET runtime uses unicode (wchar_t) strings, not ascii (char) so this require some changes. You should also consider that .NET has no way to free a string that has been allocated by a C/C++ application, so having the buffer pre-allocated and passed in from C# is the only safe way to manage this without memory leaks or worse.

    0 讨论(0)
提交回复
热议问题