Marshal an array of strings from C# to C code using p/invoke

后端 未结 3 1280
广开言路
广开言路 2020-12-11 10:39

I need to pass an array of C# strings into C code

Example C code

void print_string_array(const char** str_array, int length){
    for (int i = 0; i &         


        
相关标签:
3条回答
  • 2020-12-11 11:04

    Why the "print_string_array(IntPtr sa, int length);" instead of "print_string_array(IntPtr[] sa, int length);" ? And what does print_string_array look at the C-side? print_string_array(char** sa, int length); ?

    0 讨论(0)
  • 2020-12-11 11:08

    You can simply declare your function in C# like this:

    [DllImport(my_C_dll, CallingConvention=CallingConvention.Cdecl)]
    static extern void print_string_array([In] string[] str_array, IntPtr length);
    

    As it is written, your C++ code would appear to use the cdecl calling convention. So you may need to make the C# declaration match. I suspect that is the main problem you are facing.

    Note also that size_t, which you use for the length parameter is 32 bits wide in a 32 bit process, and 64 bits wide in a 64 bit process. So the correct C# type is IntPtr. Personally I'd declare it to be int in both the C++ and C# code.


    One final word of advice. When you encounter failures, include the error messages in your questions. I suspect your first code failed with this error:

    A call to PInvoke function 'MyApp!MyApp.Program::print_string_array' has unbalanced the stack.

    And if you had included that in the question it would have been a great help.

    0 讨论(0)
  • 2020-12-11 11:18

    Your second attempt is quite close. Try the following:

    string[] foo = {"testing", "one", "two", "three"};  
    IntPtr[] s_array = new IntPtr[foo.Length];
    
    for(int i = 0; i < foo.Length; ++i) 
    {
        s_array[i] = Marshal.StringToHGlobalAnsi(foo[i])
    }
    GCHandle gH = GCHandle.Alloc(s_array, GCHandleType.Pinned);
    print_string_array( gH.AddrOfPinnedObject(), s_array.Length);
    gH.Free();
    for(int i = 0; i < foo.Length; ++i) 
    {
        Marshal.FreeHGlobal(s_array[i])
    }
    
    [DllImport(my_C_dll, CharSet = CharSet.Ansi)]
    private static extern int print_string_array(IntPtr sa, int length);
    
    0 讨论(0)
提交回复
热议问题