1

I need to send a struct from C# managed code to a C library. The C library will populate the values in the struct. I have been trying to pass the struct as a reference so that the C# code will get the updated data values.

This is an example C function in libshlib.so:

void sharedStruct(struct data* d)
{
   d->number = calcSomething();
   d->message = doSomething();
}

I can send individual parameters (int and StringBuilder) and the library code runs and returns new values to the C# code that called it.

But how can I create a struct in C# that contains both int and string and send it to the unmanaged code (C library) which will populate the values to be used back in the C# code?

The C struct might be like this:

struct data
{
  int number;
  char* message;
};

Right now I'm trying to establish the best way to manipulate data in the C library for use in C#. I am writing both pieces of code so I am flexible but right now I haven't been able to get it working.

1
  • Can you show us the C struct? Commented May 9, 2013 at 19:26

1 Answer 1

1

If you want the struct to be populated by the C code, then you are probably looking for an out variable. Note that the mono runtime by default will use free() to deallocate any strings you pass in and you might have to take extra care with padding in structures (see the StructLayout stuff in msdn). For strings, further problems can be had with character sets.

Sample code:

Managed.cs:

using System;
using System.Runtime.InteropServices;

struct Data
{
    public int number;
    public string message;
}

class Managed
{
    [DllImport("unmanaged")]
    extern static void Foo(out Data data);
    static void Main()
    {
        Data data;
        Foo(out data);
        Console.WriteLine("number = {0}, message = {1}", data.number, data.message);
    }
}

unmanaged.c:

#include <string.h>

struct data
{
    int number;
    char* message;
};

void Foo(struct data* data)
{
    data->number = 42;
    data->message = strdup("Hello from unmanaged code!");
}

Test run:

$ mcs Managed.cs
$ gcc -shared -fPIC -o libunmanaged.so unmanaged.c
$ LD_LIBRARY_PATH=$PWD mono Managed.exe
number = 42, message = Hello from unmanaged code!
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, could it be that easy??!! Thanks for posting all of the details. After many tries I had finally specified MarshallAs for both number and message, passed the struct as ref and found that I had to initialize message for it to work. And I did also use: [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Ansi)]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.