0

How can I using Dllimport by C# to get string array from C library

int GetClasses (int *NumberofClasses, char *ClassNames[], int arrayLength)

I have try StringBuilder[] and many of MarshalAsAttributes to receive ClassNames but still not work and cause memory violation

I have only explanation of this C method is showing below.

int GetClasses(int * NumberofClasses, char * ClassNames[], int arrayLength)

This function will get the total number of unique classes and each unique class name.

Parameters:
NumberofClasses: Total number of unique classes.
ClassNames: Array of allocated char * to return class names.
arrayLength: Length of passed ClassNames array. If the result exceeds this array length, this function will fail with an error code.

Returns: Zero for success. Non-zero for error

And my declaration is

[DllImport(@".\library.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern Int16 GetClasses(ref UInt16 NumberofClasses, StringBuilder[]  ClassNames, UInt16 arrayLength);

I have pass

NumberofClasses=16,

ClassNames= StringBuilder[16] with 256 capacity of each

arrayLength=16

to this call

David1979
  • 9
  • 4
  • 1
    You neeed to know the excact contract assumed by the function. Probably the caller needs to pass an array of `arrayLength` `char*` pointers. Will the function allocate memory for the individual strings and put the pointers into the array? If yes: how exactly does the C library allocate the memory? The caller might have to free this memory again. Here is a similayr question: https://stackoverflow.com/questions/23219625/what-type-to-pinvoke-for-a-char – Klaus Gütter Jul 27 '22 at 05:24
  • Show an example of how is your C code is written. – Simon Mourier Jul 27 '22 at 06:25
  • I don't have the C library source code. The library is provided by supplier and can't get any more information from supplier. – David1979 Jul 27 '22 at 06:28
  • What made you think int maps to Int16? Anyway the easiest way to proceed here is to write some C code that calls it successfully. And then learn from that. – David Heffernan Jul 27 '22 at 08:18
  • Because the supplier provided some C# sample code before. In the sample int is mapped to Int16 and the call runs successfully. – David1979 Jul 27 '22 at 08:34
  • Well Int16 is wrong, it should be int which is a 32 bit integer. I still feel that getting this working with C code would clear things up. Surely the supplier has examples of that. You also didn't show your code to make the call. Who knows if that was done correctly. – David Heffernan Jul 27 '22 at 10:45

1 Answers1

0

Finally I got the success call by modify the declaration of parameter type.

[DllImport(@".\library.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    private static extern Int16 GetClasses(ref UInt16 NumberofClasses, [In][Out][MarshalAs(UnmanagedType.LPArray)] string[] ClassNames, UInt16 arrayLength);

And allocate a string array to parameter ClassNames

string[] names = new string[NumberOfClasses];

for (int i = 0; i < names.Length; i++)
{
    names[i] = new string(new char[256]);
}
David1979
  • 9
  • 4