[Mono-list] Problems Using P/Invoke

Jonathan Pryor jonpryor at vt.edu
Thu Nov 10 16:53:22 EST 2005


On Thu, 2005-11-10 at 23:51 +0800, Jeremy Tan wrote:
> I am trying to write some C# bindings for the C++ libdar library
> (http://dar.sourceforge.net)...
> The problem I am having now is that I can't seem to find a way
> to bind this library into C# APIs due to the way the functions are
> declared. I've tried searching the internet but I can't seem to find any
> information on this.

	http://www.mono-project.com/dllimport

> I'm stuck at the first function that I'm trying to
> import and I can't go any further from this point as almost all the
> functions in the library are declared this way:
> 
> extern void get_compile_time_features(bool & ea, 
> 	bool & largefile, 
> 	bool & nodump, 
> 	bool & special_alloc, 
> 	U_I & bits, 
> 	bool & thread_safe,
>         bool & libz, 
> 	bool & libbz2, 
> 	bool & libcrypto);
> 
> The problem I have here is the way the parameters are defined. Note that
> the U_I type is just a typedef to unsigned int in libdar. In my source
> file, i declared it like this because I can't seem to find a way to
> specify "&" in the method signature:

`ref' is an appropriate mapping for `&'.  You have several other
problems...

> [DllImport(library, CallingConvention = CallingConvention.Cdecl)]
>             private unsafe extern static void get_compile_time_features(
>                     ref bool EAttributes,
>                     ref bool LFile,
>                     ref bool NDunp,
>                     ref bool SAllocation,
>                     ref uint bits,
>                     ref bool TSafe,
>                     ref bool LZ,
>                     ref bool LBZ2,
>                     ref bool LCrypto);

starting with this:

> Unhandled Exception: System.EntryPointNotFoundException:
> get_compile_time_features
> in (wrapper managed-to-native) LibDar.LibDar:get_compile_time_features
> (bool&,bool&,bool&,bool&,uint&,bool&,bool&,bool&,bool&)
> in <0x00054> LibDar.LibDar:GetCompileTimeFeatures ()
> in <0x00026> LibDar.Tester:Main (System.String[] args)

The problem is C++ name mangling.  For "fun" run the nm(1) command on
your C++ library.  The get_compile_time_features function is actually
the symbol _Z25get_compile_time_featuresRbS_S_S_RjS_S_S_S_ in your
library (or something similarly FUBAR).  Mono/.NET do not understand C++
name mangling conventions (there'd be little point, since each C++
compiler has a different name mangling scheme).

The solution to this is ``extern "C"''.  You'd have to either change the
get_compile_time_features declaration to this:

        extern "C" void get_compile_time_features(bool & ea, 
        	bool & largefile, 
        	bool & nodump, 
        	bool & special_alloc, 
        	U_I & bits, 
        	bool & thread_safe,
                bool & libz, 
        	bool & libbz2, 
        	bool & libcrypto);

or you'd have to write a C wrapper for the C++ function.

The other problem you have is "bool".  The size of "bool" varies between
compilers, and Mono marshals it as a short, which probably isn't what
the C++ compiler uses.  Thus you have to determine what sizeof(bool) is
for your C++ compiler and use an appropriate type in your C#
declaration.

You may find SWIG to be useful: http://www.swig.org

 - Jon




More information about the Mono-list mailing list