Mono and Unmanaged Code in Ubuntu

mono and unmanaged code in ubuntu

It should be

[DllImport("libc.so.6")]

or just

[DllImport("libc")]

"libc" is a alias from /etc/mono/config,
On GNU/Linux system:

...
<dllmap dll="libc" target="libc.so.6" os="!windows"\>
...

How to use LuaInterface on Mono/Linux

LuaInterface looks to be pure C#, but it uses a mixed mode C++/CLI-ified version of the Windows version of the native Lua library, that mixes .NEt code and native 32-bit Windows code. There's no C++/CLI compiler for platforms other than Windows, so you can't port/recompile the C++/CLI code, though it should work on Mono on Win32 (or maybe Wine)..

The only really viable way to get this to work on Mono would be to make it use P/Invokes istead of C++/CLI. You could then use a dllmap so that when Mono tries to resolve the P/Invoke calls to lua51.dll, it is redirected to the Linux equivalent, liblua.so.5.1.

Cannot access a Linux gcc compiled .so shared library from Windows Mono C# Project

You can't use a .so elf binary on Windows for your native code. You need to recompile it into a native binary supported by Windows (namely a .dll).

I suggest you read our wiki page about cross platform interop between managed an unmanaged code.

Linux, Mono, shared libs and unresolved symbols

You should specify the dependency when you link the wrapper library like

g++ -shared -Wl,-soname,libexif-wrapper.so.1 -o libexif-wrapper.so.1.0.1 libexif-wrapper.o -lc -lexif

When you do that the dynamic linker knows that libexif-wrapper depends on libexif and it can resolve the symbols on load.

Mono native binary bundle fails to load libc in newer Linux kernels

The root cause of the problem was that Mono was looking for libc.so where the OS only had libc.so.6. Mono needs a DllMap config file to understand how to translate this.

The solution to the problem was to add the default Mono3 DllMap config file to the same directory as my binary. Sadly it appears that Mono doesn't cache the DllMap globally for the process, so I had to make multiple duplicate copies of the config file under the different names of the various modules that were being called. For example:

Mono.Posix.dll.config
System.Drawing.dll.config
System.Windows.Forms.dll.config

in linux, mono invoke my .so lib return System.EntryPointNotFoundException

There are a couple of reasons why your code doesn't work:

  1. The function c_meth does not exist within your shared library. The function that does exist is _Z6c_methNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE.
  2. The C++ class std::string and the .NET class System.String are different and entirely unrelated. .NET only knows how to marshal System.String to const char* and vice versa.

C++ allows function overloading. That means it needs a way to tell void foo(int) apart from void foo(std::string). To do this, it uses name mangling to generate a unique name for each overload. To disable name mangling for a function you declare it with the extern "C" specifier. This also limits you to C-like interfaces, so you can only pass and return primitive objects and pointers. No classes or references. That's fine though, since .NET doesn't know what to do with C++ classes. You need to accept a raw const char* parameter and return a const char*:

extern "C" const char* c_meth(const char* str_arg) {
return "prpr";
}

Returning strings is also problematic. .NET will try to de-allocate the returned memory after copying the string to the managed heap. Since the string returned in this case wasn't allocated using the appropriate allocation method, that will fail. To avoid this you'll need to declare the imported method in C# to return an IntPtr and use Marshal.PtrToString(Ansi|Unicode) to convert to a System.String.

If you do need to return something other than a string constant, you have a couple options:

  1. Allocate the memory for the string with the appropriate function. The function to use is platform-dependent. See Mono's documentation for info about which function to use.
  2. Allocate the memory in C# and pass the buffer to the unmanaged function using a System.Text.StringBuilder:

C++ side:

extern "C" void c_meth(const char* str_arg, char* outbuf, int outsize) {
std::string ret = someFunctionThatReturnsAString(str_arg);
std::strncpy(outbuf, ret.c_str(), outsize);
}

C# side:

[Test]
public void TestDraft()
{
StringBuilder sb = new StringBuilder(256)
c_meth("prpr", sb, 256);
Console.WriteLine(sb.ToString());
}

[DllImport("/home/roroco/Dropbox/cs/App.Switcher/c/app-switcher/lib/libapp-switcher-t.so")]
private static extern void c_meth(string strArg, StringBuilder outbuf, int outsize);


Related Topics



Leave a reply



Submit