fsp
fsp

Reputation: 515

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.

Upvotes: 1

Views: 3240

Answers (1)

NineBerry
NineBerry

Reputation: 28499

Declare the structs like this:

 public unsafe struct CustomerInfo
 {
      public sbyte* Id;
      public sbyte* Name;
      public sbyte* Address;
 }

 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);

Upvotes: 2

Related Questions