Create a dll from MinGW and call it from .NET/csharp

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Create a dll from MinGW and call it from .NET/csharp

Frank Hrebabetzky-2
Posted a similar question on the Codeguru site; as things still don't
work I am suspecting an error on the native dll side.

Problem: I wasn't capable to call a native library (GSL) from a C#
program running on .NET. So I wrote a simple C program with similar
prototypes, compiled it with  MinGW/gcc into a native dll, wrote a test
program in the same way which calls the dll, and wrote another test
program in C# under .NET which calls it too. Result: calling the dll
from the C test program running under MSys works, calling it from .NET
doesn't; it compiles, but I get a null reference error message at runtime.

The header file contents of my library 'generic.h' is

> #ifdef BUILD_DLL
> // the dll exports
> #define EXPORT __declspec(dllexport)
> #else
> // the exe imports
> #define EXPORT __declspec(dllimport)
> #endif
>
> EXPORT
> double average ( // returns average of f
> double (*f) (double x, void *params),
> void *par, // the parameters of f
> double a, // interval
> double b,
> int n // # of function values
> );

The C test program 'testgeneric.c' calls it like this:

> #include "generic.h"
>
> struct Par3 {double a, b, c;};
>
> double quadratic (double x, void *par)
> { double *p;
>   p = par;
>   return (*p * x + *(p+1)) * x + *(p+2);
> }
>
> int main (void)
> {
>   struct Par3 params = {1.0, 0.0, -5.0};
>
>   printf("Average in [0,2] (10 points): %f\n",
> average (&quadratic, &params, 0.0, 2.0, 10));
>   return 0;
> }

and the makefile is

> # To compile with debug option, call "make DEBUG=-g"
>
> testgeneric.exe: testgeneric.o generic.dll
> gcc -o testgeneric.exe testgeneric.o -L./ -lgeneric $(DEBUG)
>
> testgeneric.o: testgeneric.c
> gcc -c testgeneric.c $(DEBUG)
>
> generic.dll: generic.o
> gcc -shared -o generic.dll -Wl,--out-implib,libgeneric.a generic.o
> cp -f generic.dll TestSharp/bin/Debug
>
> generic.o: generic.h generic.c
> gcc -c generic.c -DBUILD_DLL -o generic.o $(DEBUG)

The C# program finally is

> using System;
> using System.Runtime.InteropServices;
>
> namespace TestSharp
> {
> class MainClass
> {
>   [StructLayout (LayoutKind.Sequential)]
>   struct Parameters { public double a, b, c; }
>
>   delegate double Func (double x, ref Parameters p);
>
>   [DllImport ("generic.dll")] static extern
>   double average (Func f, ref Parameters p, double a, double b, int n);
>
>   static double Quadratic (double x, ref Parameters p)
>   { return (p.a*x + p.b)*x + p.c;}
>
>   public static void Main(string[] args)
>   {
>     Parameters par;
>     Func func;
>     double avg;
>
>     par = new Parameters();
>     { par.a = 1;  par.b = 0;  par.c=-5;}
>     func = new Func (Quadratic);
>     avg = average (func, ref par, 0.0, 2.0, 10);
>     Console.WriteLine("Average in [0,2] (10 points): " + avg.ToString() +"\r\n");
>     Console.WriteLine("RETURN to terminate ...");
>     Console.ReadLine();
>   }
> }
> }

It compiles but reports the following runtime error:

> Exception System.ExecutionEngineException was thrown in debuggee:
> <null reference>
>
> Main() - c:\Documents and Settings\Frank\My Documents\Exercises\C\GSL\Generic\TestSharp\Main.cs:28,5

Line 28 is the one which goes 'avg = average (func, ref par, ...'.
When looking at it with a debugger, 'func' and 'par' aren't null.

Any idea what might be wrong?

Or how to debug such a thing?

Thanks in advance.
--
Frank Hrebabetzky Tel. (48) 3239 2258
Photonita Ltda. http://www.photonita.com.br
Brazil


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
MinGW-users mailing list
[hidden email]

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|

Re: Create a dll from MinGW and call it from .NET/csharp

Earnie Boyd

Quoting Frank Hrebabetzky <[hidden email]>:

> Posted a similar question on the Codeguru site; as things still don't
> work I am suspecting an error on the native dll side.
>
> Problem: I wasn't capable to call a native library (GSL) from a C#
> program running on .NET. So I wrote a simple C program with similar
> prototypes, compiled it with  MinGW/gcc into a native dll, wrote a test
> program in the same way which calls the dll, and wrote another test
> program in C# under .NET which calls it too. Result: calling the dll
> from the C test program running under MSys works, calling it from .NET
> doesn't; it compiles, but I get a null reference error message at runtime.
>
> The header file contents of my library 'generic.h' is
>
>> #ifdef BUILD_DLL
>> // the dll exports
>> #define EXPORT __declspec(dllexport)
>> #else
>> // the exe imports
>> #define EXPORT __declspec(dllimport)
>> #endif
>>
>> EXPORT
>> double average ( // returns average of f
>> double (*f) (double x, void *params),
>> void *par, // the parameters of f
>> double a, // interval
>> double b,
>> int n // # of function values
>> );
>
> The C test program 'testgeneric.c' calls it like this:
>
>> #include "generic.h"
>>
>> struct Par3 {double a, b, c;};
>>
>> double quadratic (double x, void *par)
>> { double *p;
>>   p = par;
>>   return (*p * x + *(p+1)) * x + *(p+2);
>> }
>>
>> int main (void)
>> {
>>   struct Par3 params = {1.0, 0.0, -5.0};
>>
>>   printf("Average in [0,2] (10 points): %f\n",
>> average (&quadratic, &params, 0.0, 2.0, 10));
>>   return 0;
>> }
>
> and the makefile is
>
>> # To compile with debug option, call "make DEBUG=-g"
>>
>> testgeneric.exe: testgeneric.o generic.dll
>> gcc -o testgeneric.exe testgeneric.o -L./ -lgeneric $(DEBUG)
>>
>> testgeneric.o: testgeneric.c
>> gcc -c testgeneric.c $(DEBUG)
>>
>> generic.dll: generic.o
>> gcc -shared -o generic.dll -Wl,--out-implib,libgeneric.a generic.o
>> cp -f generic.dll TestSharp/bin/Debug
>>
>> generic.o: generic.h generic.c
>> gcc -c generic.c -DBUILD_DLL -o generic.o $(DEBUG)
>
> The C# program finally is
>
>> using System;
>> using System.Runtime.InteropServices;
>>
>> namespace TestSharp
>> {
>> class MainClass
>> {
>>   [StructLayout (LayoutKind.Sequential)]
>>   struct Parameters { public double a, b, c; }
>>
>>   delegate double Func (double x, ref Parameters p);
>>
>>   [DllImport ("generic.dll")] static extern
>>   double average (Func f, ref Parameters p, double a, double b, int n);
>>
>>   static double Quadratic (double x, ref Parameters p)
>>   { return (p.a*x + p.b)*x + p.c;}
>>
>>   public static void Main(string[] args)
>>   {
>>     Parameters par;
>>     Func func;
>>     double avg;
>>
>>     par = new Parameters();
>>     { par.a = 1;  par.b = 0;  par.c=-5;}
>>     func = new Func (Quadratic);
>>     avg = average (func, ref par, 0.0, 2.0, 10);
>>     Console.WriteLine("Average in [0,2] (10 points): " +
>> avg.ToString() +"\r\n");
>>     Console.WriteLine("RETURN to terminate ...");
>>     Console.ReadLine();
>>   }
>> }
>> }
>
> It compiles but reports the following runtime error:
>
>> Exception System.ExecutionEngineException was thrown in debuggee:
>> <null reference>
>>
>> Main() - c:\Documents and Settings\Frank\My
>> Documents\Exercises\C\GSL\Generic\TestSharp\Main.cs:28,5
>
> Line 28 is the one which goes 'avg = average (func, ref par, ...'.
> When looking at it with a debugger, 'func' and 'par' aren't null.
>
> Any idea what might be wrong?
>

I see the declaration of average but not the definition.  Where's the
definition?

> Or how to debug such a thing?
>

http://www.google.com/search?q=outputdebugstring+site%3Amicrosoft.com

Earnie

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
MinGW-users mailing list
[hidden email]

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|

Re: Create a dll from MinGW and call it from .NET/csharp

Frank Hrebabetzky-2
Earnie Boyd wrote:

> Quoting Frank Hrebabetzky <[hidden email]>:
>
>> Posted a similar question on the Codeguru site; as things still don't
>> work I am suspecting an error on the native dll side.
>>
>> Problem: I wasn't capable to call a native library (GSL) from a C#
>> program running on .NET. So I wrote a simple C program with similar
>> prototypes, compiled it with  MinGW/gcc into a native dll, wrote a test
>> program in the same way which calls the dll, and wrote another test
>> program in C# under .NET which calls it too. Result: calling the dll
>> from the C test program running under MSys works, calling it from .NET
>> doesn't; it compiles, but I get a null reference error message at runtime.
>>
>> The header file contents of my library 'generic.h' is
>>
>>> #ifdef BUILD_DLL
>>> // the dll exports
>>> #define EXPORT __declspec(dllexport)
>>> #else
>>> // the exe imports
>>> #define EXPORT __declspec(dllimport)
>>> #endif
>>>
>>> EXPORT
>>> double average ( // returns average of f
>>> double (*f) (double x, void *params),
>>> void *par, // the parameters of f
>>> double a, // interval
>>> double b,
>>> int n // # of function values
>>> );
>> The C test program 'testgeneric.c' calls it like this:
>>
>>> #include "generic.h"
>>>
>>> struct Par3 {double a, b, c;};
>>>
>>> double quadratic (double x, void *par)
>>> { double *p;
>>>   p = par;
>>>   return (*p * x + *(p+1)) * x + *(p+2);
>>> }
>>>
>>> int main (void)
>>> {
>>>   struct Par3 params = {1.0, 0.0, -5.0};
>>>
>>>   printf("Average in [0,2] (10 points): %f\n",
>>> average (&quadratic, &params, 0.0, 2.0, 10));
>>>   return 0;
>>> }
>> and the makefile is
>>
>>> # To compile with debug option, call "make DEBUG=-g"
>>>
>>> testgeneric.exe: testgeneric.o generic.dll
>>> gcc -o testgeneric.exe testgeneric.o -L./ -lgeneric $(DEBUG)
>>>
>>> testgeneric.o: testgeneric.c
>>> gcc -c testgeneric.c $(DEBUG)
>>>
>>> generic.dll: generic.o
>>> gcc -shared -o generic.dll -Wl,--out-implib,libgeneric.a generic.o
>>> cp -f generic.dll TestSharp/bin/Debug
>>>
>>> generic.o: generic.h generic.c
>>> gcc -c generic.c -DBUILD_DLL -o generic.o $(DEBUG)
>> The C# program finally is
>>
>>> using System;
>>> using System.Runtime.InteropServices;
>>>
>>> namespace TestSharp
>>> {
>>> class MainClass
>>> {
>>>   [StructLayout (LayoutKind.Sequential)]
>>>   struct Parameters { public double a, b, c; }
>>>
>>>   delegate double Func (double x, ref Parameters p);
>>>
>>>   [DllImport ("generic.dll")] static extern
>>>   double average (Func f, ref Parameters p, double a, double b, int n);
>>>
>>>   static double Quadratic (double x, ref Parameters p)
>>>   { return (p.a*x + p.b)*x + p.c;}
>>>
>>>   public static void Main(string[] args)
>>>   {
>>>     Parameters par;
>>>     Func func;
>>>     double avg;
>>>
>>>     par = new Parameters();
>>>     { par.a = 1;  par.b = 0;  par.c=-5;}
>>>     func = new Func (Quadratic);
>>>     avg = average (func, ref par, 0.0, 2.0, 10);
>>>     Console.WriteLine("Average in [0,2] (10 points): " +
>>> avg.ToString() +"\r\n");
>>>     Console.WriteLine("RETURN to terminate ...");
>>>     Console.ReadLine();
>>>   }
>>> }
>>> }
>> It compiles but reports the following runtime error:
>>
>>> Exception System.ExecutionEngineException was thrown in debuggee:
>>> <null reference>
>>>
>>> Main() - c:\Documents and Settings\Frank\My
>>> Documents\Exercises\C\GSL\Generic\TestSharp\Main.cs:28,5
>> Line 28 is the one which goes 'avg = average (func, ref par, ...'.
>> When looking at it with a debugger, 'func' and 'par' aren't null.
>>
>> Any idea what might be wrong?
>>
>
> I see the declaration of average but not the definition.  Where's the
> definition?
>
>> Or how to debug such a thing?
>>
>
> http://www.google.com/search?q=outputdebugstring+site%3Amicrosoft.com
>
> Earnie
>
> -------------------------------------------------------------------------
> This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
> Build the coolest Linux based applications with Moblin SDK & win great prizes
> Grand prize is a trip for two to an Open Source event anywhere in the world
> http://moblin-contest.org/redirect.php?banner_id=100&url=/
> _______________________________________________
> MinGW-users mailing list
> [hidden email]
>
> You may change your MinGW Account Options or unsubscribe at:
> https://lists.sourceforge.net/lists/listinfo/mingw-users
>

I thought it wasn't relevant. Here it is.

> #include "generic.h"
>
> double average (double (*f) (double x, void *params),
> void *par, double a, double b, int n)
> {
>   int i;
>   double sum, x, dx;
>
>   sum = 0;   x = a;   dx = (b-a) / (n-1);
>   for (i=0; i<n; i++) { sum += f(x,par);  x += dx; }
>   return sum / n;
> }

Frank Hrebabetzky Tel. (48) 3239 2258
Photonita Ltda. http://www.photonita.com.br
Brazil


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
MinGW-users mailing list
[hidden email]

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|

Re: Create a dll from MinGW and call it from .NET/csharp

Jef Driesen
In reply to this post by Frank Hrebabetzky-2
Frank Hrebabetzky wrote:

> Posted a similar question on the Codeguru site; as things still don't
> work I am suspecting an error on the native dll side.
>
> Problem: I wasn't capable to call a native library (GSL) from a C#
> program running on .NET. So I wrote a simple C program with similar
> prototypes, compiled it with  MinGW/gcc into a native dll, wrote a test
> program in the same way which calls the dll, and wrote another test
> program in C# under .NET which calls it too. Result: calling the dll
> from the C test program running under MSys works, calling it from .NET
> doesn't; it compiles, but I get a null reference error message at runtime.

I did run into the same problem some time ago, see here:

http://www.nabble.com/Using-a-mingw-DLL-from-C--td18586582.html

The problem is caused by the difference in calling convention between
the C DLL (cdecl) and the C# callback function (stdcall). You have to
change the calling convention of the callback function to cdecl (.NET
2.x or higher only):

[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
delegate double Func (double x, ref Parameters p);

Or change the C DLL to expect a stdcall callback function of course.


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
MinGW-users mailing list
[hidden email]

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|

Re: Create a dll from MinGW and call it from .NET/csharp

Frank Hrebabetzky-2
This list observes the Etiquette found at http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.
_______________________________________________
Jef Driesen wrote:
> The problem is caused by the difference in calling convention between
> the C DLL (cdecl) and the C# callback function (stdcall). You have to
> change the calling convention of the callback function to cdecl (.NET
> 2.x or higher only):
>
> [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
> delegate double Func (double x, ref Parameters p);
>
> Or change the C DLL to expect a stdcall callback function of course.

Thanks a lot for the hint. It works now.
--
Frank Hrebabetzky Tel. (48) 3239 2258
Photonita Ltda. http://www.photonita.com.br
Brazil


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
MinGW-users mailing list
[hidden email]

You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users