How can i pass structure into c function that expect pointer

G

guy.gorodish

hi,
i have couple of qeustions:

1. I have built a interop of c dll. In this dll i have a function that
expect a pointer to a struct.
I want to pass a struct from my c# interop into this c function. how
can I change my c# struct into a pointer that i could send to the c
function?

2. how can i send a null to this function that ecpect pointer to
struct?

Appreciate help,
Guy
 
F

Fred Mellender

I had a similar problem: I wanted to access the GNU MP library (infinite
precision arithmetic, http://gmplib.org/, ) via a C# class. To solve the
problem, I used VS C++. This allows you to create a .NET class that can be
accessed by C#, but that can contain pointers to structures.

The header file for GMP is gmp.h and contains the various C++ data types.
This
is the only GMP source you need (a dll for Visual C++ is available, see
below).

I defined a .h header file that included gmp.h and that also defined a "C++"
class, GMP. Some of the code therein looks like:


using namespace System;
using namespace System::Runtime::InteropServices;
#include "gmp.h"

typedef __mpz_struct * mpzPtr_t;
#define OTHER_MPZ(obj) ((mpzPtr_t)(obj->mpzPtr))
#define THIS_MPZ ((mpzPtr_t)(mpzPtr))

namespace gmpX {

public class GMP
{
public:
[DllImport("gmp.dll")]
static void mpz_add(mpz_t addIn, mpz_t add1, mpz_t add2);

[DllImport("gmp.dll")]
static void mpz_addmul_ui(mpz_t addIn, mpz_t mult1, unsigned long int
mult2);


...... and many more functions, corresponding to the C functions in gmp.h.
These do the multiple precision arithmetic.

I then defined a GmpInt class to be accessed via C# as:

public ref class GmpInt: IDisposable
{
private:
unsigned long mpzPtr;
public:
GmpInt();
GmpInt(unsigned int initVal);
GmpInt(int initVal);
~GmpInt();

double asDouble();

String ^ asString();

int asInt();

void add(GmpInt^ add1, GmpInt^ add2);

... and more functions corr. to the functions I needed. This class
represents an integer that can have as many digits as required. Note the
use of GmpInt^ to define the input. This allows C++ to look at the objects
as "pointers" to the corresponding C# object. Note the mpzPtr defined as an
unsigned long. This is a pointer to the C++ structure that GMP passes
around to do the arithmetic.

You define the functions for class GmpInt are defined in a .cpp file thus:


#include <malloc.h>
#include "stdafx.h"

#include "gmpX.h"


using namespace gmpX;

//3 constructors.
GmpInt::GmpInt()
{
mpzPtr_t bitPtr = new __mpz_struct;
mpzPtr = (unsigned long)bitPtr;
GMP::mpz_init(bitPtr);
}

GmpInt::GmpInt(unsigned int iVal)
{
mpzPtr_t bitPtr = new __mpz_struct;
mpzPtr = (unsigned long)bitPtr;
GMP::mpz_init_set_ui(bitPtr, iVal);
}

GmpInt::GmpInt(int iVal)
{
mpzPtr_t bitPtr = new __mpz_struct;
mpzPtr = (unsigned long)bitPtr;
GMP::mpz_init_set_si(bitPtr, iVal);
}

GmpInt::~GmpInt() //remember: this destructor is called upon Dispose
{
GMP::mpz_clear((mpz_ptr)mpzPtr);
delete (mpzPtr_t)mpzPtr;
}


void GmpInt::add(GmpInt^ add1, GmpInt^ add2) //add to big ints.
{
GMP::mpz_add(THIS_MPZ, OTHER_MPZ(add1), OTHER_MPZ(add2));
}

void GmpInt::addMultiply(GmpInt^ mult1, unsigned int mult2)
{
GMP::mpz_addmul_ui(THIS_MPZ, OTHER_MPZ(mult1), mult2);
}



..... and other functions similarly implemented by
calling the C++ function in the dll.

The GMP C dll for VS is available on the net, precompiled and ready to go:
http://www.cs.nyu.edu/exact/core/gmp/


If you do not have VS for C++, you can download a free "Express" version
from MS:
http://msdn.microsoft.com/vstudio/express/visualc/
 
R

rossum

hi,
i have couple of qeustions:

1. I have built a interop of c dll. In this dll i have a function that
expect a pointer to a struct.
I want to pass a struct from my c# interop into this c function. how
can I change my c# struct into a pointer that i could send to the c
function?
Have you tried unsafe and fixed?

myData thisStuff = new myData();
unsafe {
fixed (myData* ptr = &thisStuff) {
c_library_function(ptr);
}
}
2. how can i send a null to this function that ecpect pointer to
struct?
This compiles - you don't need the fixed statement because null is
inherently fixed as it does not live on the managed heap:

unsafe {
int* voidPtr = null;
c_library_function(voidPtr);
}

rossum
 

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