trouble witch using struct from C dll

Y

yucikala

Hello, I'm a "expert of beginner" in C#.
I have a dll - in C. And in this dll is this struct:


typedef
struct msg_s { /* please make duplicates of strings before next call
to emi_read() ! */

int op_type; /* of "op_t" type: operation type; submit (>0), response
(<0) */

union {

struct {

const char* from;
const char* to;
const char* notif_addr;
int notif_type; /* not_t */
const char* validity; /* DDMMYYHHmm */
const char* timestamp; /* DDMMYYHHmmss */
dst_t deliv_status;
int deliv_reasoncode;
const char* deliv_timestamp; /* DDMMYYHHmmss */
const char* text;
int priority;
int bit8; /* data coding scheme */
int numbits; /* number of bits in TD (text) if bit8=1 */
int msg_class;
int rpid; /* rpid == -1 => use RPID value "0000" */
/* rpid == 0 => do not use RPID value */
const char* xservices; /* extra services */
} submit;
struct {
int ack;
int errcode;
const char* sysmsg;
} response;
} uu;
} msg_t;

How can I use this struct in C#?
How can I make in C# the same code as is in C:

msg_t* msg = 0;
msg = emi_msg( emi); //emi_msg is a function whitch return a pointer
optyp = msg->op_type;


Thanks a lot

Pavel Spaleny
 
P

per9000

Hi Pavel,

I borrowed an example that is originally from http://www.ddj.com/dept/windows/184406285
to get a small example that works

---------------------------------------------------
// C-code
#include <stdio.h>
#include <math.h>

typedef struct { double re,im; } Complex;

__declspec(dllexport) void __stdcall MakeComplex(Complex * C)
{
C = (Complex*) malloc(sizeof(Complex));
C->re = 0.0;
C->im = 0.0;
}

__declspec(dllexport) void __stdcall KillComplex(Complex * c)
{
free(c);
}

__declspec(dllexport) void __stdcall PlayComplex(Complex * C)
{

printf("Re = %f\n", C->re);
printf("Im = %f\n", C->im);
printf("Abs = %f\n", sqrt(C->re*C->re + C->im*C->im));
}
---------------------------------------------------
// C#-code
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct Complex
{
// if these two lines are swapped - we swap(re,im)
public double re;
public double im;
};


public class myComplex
{
[DllImport("cplx")]
public static extern void MakeComplex(out Complex C);

[DllImport("cplx")]
public static extern void KillComplex(ref Complex C);

[DllImport("cplx")]
public static extern void PlayComplex(ref Complex C);


public static void Main()
{
Complex C = new Complex();
C.re = 1.0;
C.im = 2.0;

PlayComplex(ref C);
Console.WriteLine("C = ({0},{1}i)", C.re, C.im);

Complex C2;
MakeComplex(out C2);
Console.WriteLine("first C2 = ({0},{1}i)",C2.re,C2.im);

C2.re = 2.2;
C2.im = -1.2;
Console.WriteLine("then C2 = ({0},{1}i)",C2.re,C2.im);
PlayComplex(ref C2);

KillComplex(ref C2);

// risky
// PlayComplex(ref C2);
}
}
---------------------------------------------------

If the C-dll is compiled into cplx.dll an exe made from the C#-code
should produce:

Re = 1.000000
Im = 2.000000
Abs = 2.236068
C = (1,2i)
first C2 = (0,0i)
then C2 = (2.2,-1.2i)
Re = 2.200000
Im = -1.200000
Abs = 2.505993

First we create a Complex in C# called C. We give it the value (1 +
2i) and send it to the C-level in PlayComplex(ref C)

Then we create a second Complex C2 in C, this is risky I think, since
we create a "pointer" in C# but allocate memory in C. Also we later
Kill the Complex with KillComplex. There is probably no way to tell in
C# that C2 is dead. But since C is C we can call PlayComplex again
(but this is most likely really dangerous).

You have to be careful and take great car in who is allocating memory
an who is not. You can probably not allocate memory in C# with "new"
and then free is in C - even if you can you will most likely end up
getting trouble.

Also GC.KeepAlive(C) might be of interest for you if you use the
complex C in a C-dll for a long time.

Keywords that were important to me the first time i tried this are:
* [StructLayout(LayoutKind.Sequential)]
* [DllImport("cplx")]
* __declspec(dllexport)
* __stdcall

I am not sure I use them in the best way, but this short example works
for me.

Also: if you end up getting a lot of trouble and never really need the
struct in C# you could just use an IntPtr to just remember where it
is. (But that is perhaps also shadowprogramming.)


--

Per Erik Strandberg
..NET Architect - Optimization
Tomlab Optimization Inc.
http://tomopt.com/tomnet/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top