Drellgor
Drellgor

Reputation: 371

Get a C struct to remember C# changes with SWIG?

So I am trying to use a C library in C# with SWIG on Linux(MonoDevelop). Everything compiles and runs just fine, but when I call the MsgBus_UseString the console-out shows gibberish instead of "HappyHappyJoyJoy".

Here's my Main in C#:

  public static void Main (string[] args)
        {               
            SWIGTYPE_p_msgbus msgBusObj = msgbus_client.MsgBus_Create();

            ret = msgbus_client.MsgBus_setString(msgBusObj, "HappyHappyJoyJoy");
            Console.WriteLine ("Set setString ret = "+ret);

            ret = msgbus_client.MsgBus_UseString(msgBusObj);
            Console.WriteLine ("UseString ret = "+ret);
        }

Here is what the function MsgBus_UseString looks like in the C lib:

static int MsgBus_UseString( msgbus_t * pObj )
{
    if ( pObj ){
        printf("The String = %s", pObj->TheString);
        return Connect(pObj->TheString);
    }
}

The MsgBus_setString function in the C lib:

int MsgBus_setString( msgbus_t * pObj, const char * theStringIn )
{
  int status = 2;  // invalid msgbus_t pointer

  if( pObj ) {
    pObj->TheString = (char*)theStringIn;
    status = 0;
  }

  printf(fp, "pObj->TheString = %s \n", pObj->TheString);

  return status;
}

This is what my SWIG interface looks like:

/* Creates wrappers so that msgbus_client can be used in C# */
%module msgbus_client
%{
#include "msgbus_client.h"
#include "msgbus_var.h"
%}

%inline %{
typedef signed char     int8_t;
typedef short int       int16_t;
typedef int         int32_t;
typedef long long int       int64_t;
typedef unsigned char       uint8_t;
typedef unsigned short int  uint16_t;
typedef unsigned int        uint32_t;
typedef unsigned long long int  uint64_t;
typedef long int _time_t;
%}

%include "msgbus_client.h"
%include "msgbus_var.h"

Here's the typedef in the msgbus_client.h file:

typedef struct msgbus msgbus_t;

I've been struggling with this for quite some time. The printf in the MsgBus_setString function returns "HappyHappyJoyJoy" but for some reason this data is lost when calling the MsgBus_UseString function. As you can see I call them right after each other and the "set" function returns 0(no error) while the "use" function returns -1(error). This makes sense since the printf is showing that TheString is a bunch of random/unreadable characters. The msgbus struct is quite large so I'd like to avoid wrapping the entire thing, but I'll do it if there is no other way.

Not sure if it's needed but just in case, here is the create function in the C lib:

msgbus_t * MsgBus_Create()
{
    struct msgbus * pObj = NULL;

    pObj = (struct msgbus*)calloc(1, sizeof(struct msgbus));
    if ( pObj ){

        pObj->TheString = NULL;

    }

    return pObj;
}

In case it wasn't obvious I'm a SWIG newb, but based off the documentation this should work. I'm clearly missing something, but I can't seem to figure out what it is. Any help is greatly appreciated.

Edit: Thanks for the quick reply.

Here is the definition of msgbus struct:

struct msgbus{
    int             fd;             
    int             run;            
    pthread_t       thread;        
    //.           
    //.   More Stuff
    //.     
    tlv_buffer_t *  pSend;          
    tlv_buffer_t *  pResp;          

    char *          TheString;        /*!< The String */
};

The definition of the msgbus struct is in msgbus_client.c and is in the msgbus_client.h with the following typedef:

typedef struct msgbus msgbus_t;

Which was mentioned above. Here is the script that does the SWIGing:

    # Begin Swiggin! #
    echo "Starting to SWIG! ... " 
    swig -csharp -outdir msgbus_swig msgbus_client.i


    Switches="-c -I/home/includes "\
"-Wall -Wundef -Wstrict-prototypes -Wno-trigraphs  -g -Wall -D__linux__ "\


    # Build binaries #
    g++ $Switches -o "$msgbusBin/msgbus_client_wrap.o" "msgbus_client_wrap.c"

    # Generate Shared Lib #
    g++ -isystem /home/include \
-isystem /home/another/include  \
-D__packed__= -DIMAGE_APPS_PROC -DFEATURE_Q_SINGLE_LINK -DFEATURE_Q_NO_SELF_QPTR \
-DFEATURE_LINUX -DFEATURE_NATIVELINUX -DFEATURE_DSM_DUP_ITEMS -DTARGET_desktop \
-I/home/more/include -Wall -Wundef \
-Wstrict-prototypes -Wno-trigraphs  -g -Wall -D__linux__ -fpic -shared \
-L/home/lib \
-Wl,-soname,libmsgbus_client.so -o "libmsgbus_client.so" \
"$msgbusBin/msgbus_client.o" "$msgbusBin/msgbus_var.o" "$msgbusBin/msgbus_client_wrap.o" -lmificommon -lc -lrt -lpthread 

    echo "SWIG complete!"

So I copied a lot of the g++ calls from a make log so there are switches in there that I don't fully understand. Please let me know if I need to display anything else. Thanks again for all your help.

Upvotes: 0

Views: 491

Answers (1)

David J
David J

Reputation: 1564

For your string issue the problem is that you try to marshal a C# string directly to a char *. But please note char * stores a pointer and not the string itself. What you need to do is to copy the string. For that you probably also need to allocate/reserve memory.

Upvotes: 1

Related Questions