Call c++ function from c# with some difficult parameters

C

capiccc

Hello together

i just have a little bit tricky question about calling a function out
of a compiled c++ dll (which do some special mathematic thing) from a
c# application. The c# application works as cgi and should do, as
said, some mathematical iterative things (the Levenberg-Marquardt
method which try to reduce the value x^2 of a fit between a set of
data points).

For this, the c++ function in the dll is specified as follows
(declaration by documentation):

mrqmin(float x[], float y[], float sig[], int ndata, float a[], int
ia[], int ma, float **covar, float **alpha, float *chisq, void (*funcs)
(float, float [], float *, float [], int), float *alamda)

(and really declared in source code:
void NR::mrqmin(Vec_I_DP &x, Vec_I_DP &y, Vec_I_DP &sig, Vec_IO_DP &a,
Vec_I_BOOL &ia, Mat_O_DP &covar, Mat_O_DP &alpha, DP &chisq, void
funcs(const DP, Vec_I_DP &, DP &, Vec_O_DP &), DP &alamda))

That can be compiled and should work because the dll is working in
another, non c# application probably.

Now I try to declare the function of the dll through DLLImport in c#
for use with this:

[------------ c# code ---------------]
public class DllImports
{

public delegate double UebergabeFunk(double i);

[DllImport("NR.dll", EntryPoint="?fnNR@@YAHXZ")]
public static extern int fnNr();

[DllImport("NR.dll", EntryPoint="?mrqmin@NR@@YAXABV?
$NRVec@N@@00AAV2@ABV?$NRVec@_N@@AAV?$NRMat@N@@3AANP6AXN041@Z4@Z")]
public unsafe static extern void mrqmin(float[] x, float[] y,
float[] sig, int ndata, float[] a, int[] ia, int ma, float[][]* covar,
float[][]* alpha, float* chisq, UebergabeFunk func, float* alambda);

public DllImports()
{

}

public unsafe void fit(float[] x, float[] y, float[] sig, int ndata,
float[] a, int[] ia, int ma, float[][] covar, float[][] alpha, float
chisq, float alambda)
{
UebergabeFunk Uebergabe = new UebergabeFunk(this.EI);
DllImports.mrqmin(x,y,sig,ndata,a,ia,ma,&covar,&alpha,&chisq,
Uebergabe, &alambda);
}

public double EI(double i)
{
return 0;
}
}
[------------ end c# code ---------------]

This don't compile correctly, mostly of the problem that a have to
give a two dimensional array to the variables covar and alpha (these 2
arrays uses as working space in the dll for some iterative mathematics
and are described in docu with "The array covar[1..ma][1..ma],
alpha[1..ma][1..ma] are used as working space during most iterations".

Based on the declaration of function in the c++ dll, maybe someone can
give me a hint how the correct declaration of this function should
look like ? The real tricky thing here is the combination of c# and a c
++ dll with parameters that are pointer or pointer to functions.

For pointer to functions a delegate seems right, but how to declare a
pointer to a 2-dim array ? (and, at least, are c++ arrays declared
with foo[,] or with foo[][] ?)

Thanks for any hint or help,
with greetings from germany

Andre
 
S

Serge Baltic

Hello,
This don't compile correctly, mostly of the problem that a have to
give a two dimensional array to the variables covar and alpha (these 2
arrays uses as working space in the dll for some iterative mathematics
and are described in docu with "The array covar[1..ma][1..ma],
alpha[1..ma][1..ma] are used as working space during most iterations".

Basically, the C implementation typically expects to have just some memory
space allocated at the pointer. I think you should try declaring the parameter
as “ref float[]†and allocate the array to the width*height length.

I'm a little bit puzzled by the mangling you have on the method name, which
implies on that it's C++, while it should be pure C by its contract.

(H) Serg
 
B

Ben Voigt [C++ MVP]

Hello together

i just have a little bit tricky question about calling a function out
of a compiled c++ dll (which do some special mathematic thing) from a
c# application. The c# application works as cgi and should do, as
said, some mathematical iterative things (the Levenberg-Marquardt
method which try to reduce the value x^2 of a fit between a set of
data points).

For this, the c++ function in the dll is specified as follows
(declaration by documentation):

mrqmin(float x[], float y[], float sig[], int ndata, float a[], int
ia[], int ma, float **covar, float **alpha, float *chisq, void (*funcs)
(float, float [], float *, float [], int), float *alamda)

(and really declared in source code:
void NR::mrqmin(Vec_I_DP &x, Vec_I_DP &y, Vec_I_DP &sig, Vec_IO_DP &a,
Vec_I_BOOL &ia, Mat_O_DP &covar, Mat_O_DP &alpha, DP &chisq, void
funcs(const DP, Vec_I_DP &, DP &, Vec_O_DP &), DP &alamda))

You can't call native C++ member functions from C#. Use a C++/CLI wrapper
(best) or a COM wrapper.
 
C

capiccc

You can't call native C++ member functions from C#. Use a C++/CLI wrapper
(best) or a COM wrapper.

At first, thanks to Serge and Ben for their posts :)

Maybe my quote out of the source code was a little bit unlucky. The
function with is exported access within the dll to a C++ member
function, but the exported function is not part of a class structure
and a plain function only. Throughout the member function is called
inside the dll itself, I think I have nothing to do with the class
thing, this is done by the dll internal. So i don't think I need a
wrapper to the class structure.

Correctly (this was my fault i must admint) I should have quoted the
export of the function from the dll which is:

#ifdef NR_EXPORTS
#define NR_API __declspec(dllexport)
#else
#define NR_API __declspec(dllimport)
#endif

NR_API void mrqmin(Vec_I_DP &x, Vec_I_DP &y, Vec_I_DP &sig, Vec_IO_DP
&a,
Vec_I_BOOL &ia, Mat_O_DP &covar, Mat_O_DP &alpha, DP &chisq,
void funcs(const DP, Vec_I_DP &, DP &, Vec_O_DP &), DP &alamda);

I think that is the more relevant export, where the variable
declaration are defines (Vec_I_DP = float[] and so on).

Is a wrapper then needed, too ? I thought I could just import the
function from the DLL through the standard [DLLImport "foo.dll"
EntryPoint="XYZ"] Statement like other dll's ? (The only problem with
the pointers and pointer to function)

Andre
 
B

Ben Voigt [C++ MVP]

You can't call native C++ member functions from C#. Use a C++/CLI
wrapper
(best) or a COM wrapper.

At first, thanks to Serge and Ben for their posts :)

Maybe my quote out of the source code was a little bit unlucky. The
function with is exported access within the dll to a C++ member
function, but the exported function is not part of a class structure
and a plain function only. Throughout the member function is called
inside the dll itself, I think I have nothing to do with the class
thing, this is done by the dll internal. So i don't think I need a
wrapper to the class structure.

Correctly (this was my fault i must admint) I should have quoted the
export of the function from the dll which is:

#ifdef NR_EXPORTS
#define NR_API __declspec(dllexport)
#else
#define NR_API __declspec(dllimport)
#endif

NR_API void mrqmin(Vec_I_DP &x, Vec_I_DP &y, Vec_I_DP &sig, Vec_IO_DP
&a,
Vec_I_BOOL &ia, Mat_O_DP &covar, Mat_O_DP &alpha, DP &chisq,
void funcs(const DP, Vec_I_DP &, DP &, Vec_O_DP &), DP &alamda);

I think that is the more relevant export, where the variable
declaration are defines (Vec_I_DP = float[] and so on).

Is a wrapper then needed, too ? I thought I could just import the
function from the DLL through the standard [DLLImport "foo.dll"
EntryPoint="XYZ"] Statement like other dll's ? (The only problem with
the pointers and pointer to function)

It's still using references, not pointers, which are a C++-specific feature
not usable by other languages. So a wrapper would be the solution.

Note that a particular compiler MAY implement a reference argument as
syntactic sugar for an automatically dereferenced const pointer, but I don't
think this is required.
 

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