By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,244 Members | 1,972 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,244 IT Pros & Developers. It's quick & easy.

trouble witch using struct from C dll

P: n/a
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

Mar 22 '07 #1
Share this Question
Share on Google+
1 Reply


P: n/a
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/

On Mar 22, 2:26 pm, "yucik...@gmail.com" <yucik...@gmail.comwrote:
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

Mar 27 '07 #2

This discussion thread is closed

Replies have been disabled for this discussion.