user3549596 user3549596 - 1 month ago 18
C Question

C# import a structure from C DLL

I have the following C header for two structs:

struct CustomerInfo
{
char* Id;
char* Name;
char* Address;
};

struct CustomerList
{
CustomerInfo* Info;
CustomerList* Next;
};


Which is a simple list.

A function is exported so that the CustomerList is returned (or better the pointer to it)

EXPORTC CustomerList* ListCustomer(void* bankPtr)


bankPtr is a not a problem here, there is a function which will return it.

Here is how I call the function in C#:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CustomerInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public IntPtr Id;
public IntPtr Name;
public IntPtr Address;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public unsafe struct CustomerList
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
CustomerInfo* Info;
CustomerList* Next;
};

...

[DllImport("bank.dll", EntryPoint = "ListCustomer", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern Customer* _ListCustomer(int bankPtr);


Then the function itself:

public unsafe static CustomerList* ListCustomer()
{
CustomerList* c = _ListCustomer(Init());

return c;
}


But the variable
c
has not the fields that I want to access.

What is the error in my doing? Is it possible to pass a struct this way? The functions are C exported, not C++, I found some examples for C++.

Update:

I tried accessing it the following after making the changes from NineBerry:

public unsafe static CustomerList* ListCustomer()
{
CustomerList* c = _ListCustomer(Init());
Console.Write("customer list: " + (int)c);

string name = new string(c->Info->Name);

return c;
}


Which procudes this error:

CS0193 The * or -> operator must be applied to a pointer


Update #2:

Using NineBerrys approach I got it working somehow, but the pointers seem to point in the wrong directions.

I printed out name, address and id:

Name ???????t??\P???????????
adr ?????????????2?????????????
Id ????????????????????????????C:\WINDOWS\SYSTEM32\VCRUNTIME140D.dll

Name ???????t??N
adr ?????????????2???????
Id ???????????????????????▒????????


These are the results.

Answer

Declare the structs like this:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
 public unsafe struct CustomerInfo
 {
      public sbyte* Id;
      public sbyte* Name;
      public sbyte* Address;
 }

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
 public unsafe struct CustomerList
 {
      public CustomerInfo* Info;
      public CustomerList* Next;
 };

For example, to access the name of the first customer:

string name = new string(c->Info->Name);
Comments