Board index » DotNet » trouble witch using struct from C dll

trouble witch using struct from C dll

DotNet166
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


-
 

Re:trouble witch using struct from C dll

Hi Pavel,



I borrowed an example that is originally from www.ddj.com/dept/windows/184406285">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.

tomopt.com/tomnet/">tomopt.com/tomnet/











On Mar 22, 2:26 pm, "yucik...@gmail.com" <yucik...@gmail.com>wrote:

Quote
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





-