Is it possible (and if so, how) to call an external API from an ordinary command-line Mono app?
For example: I've installed Mono on my Mac via this page and have been happily writing command-line apps, but now want to access some simple CoreFoundation API. I really don't want to switch to Xamarin.Mac just for that. Is this possible?
As a closely related question, can I create my own shared library exposing a C API, and somehow invoke this from my Mono app?
The Mono Docs cover P/Invoke here : http://www.mono-project.com/docs/advanced/pinvoke/
Citing:
The Common Language Infrastructure (CLI) is designed to make it “easy” to interoperate with existing code. In principle, all you need to do is create a DllImport function declaration for the existing code to invoke, and the runtime will handle the rest. For example:
[DllImport ("libc.so")]
private static extern int getpid ();
Because you specifically asked about Mac:
Note: Mono uses GLib to load libraries, and GLib has a bug on Mac OS X where it doesn’t use a .dylib extension, but instead uses the Unix .so extension. While this should eventually be fixed, the current workaround is to write a .config file which maps to the .dylib file, e.g. [and so on ...]
Related
Is C++ source code required to build a .NET wrapper or static libraries *.lib files are just enough?
We plan to use SWIG.
Thanks.
w.r.t. your question asking specifically about static-libraries *.lib:
Is C++ source code required to build a .NET wrapper or static libraries *.lib files are just enough?
I doubt you actually intend to wrap a static-lib: Statically-linked libraries generally aren't redistributable nor portable (e.g. the authors of closed-source static libraries need to build them every time a new supported compiler comes out, e.g. you can't use a GCC lib with VisualC++ 2017, and an x64 VisualC++ 2017 lib won't be compatible with an x86 VisualC++ 2015 project) - and even if you loaded a *.lib into your process' memory and jumped into a known function address inside the lib's image, it would immediately break because the static library's code will have references to certain memory addresses (e.g. of string-constants) which aren't yet relocated - you'll get an segfault (or "Access violation" on Windows) crash if you're lucky (if not, it'll definitely corrupt your process' memory space before being detected).
P/Invoke in .NET Framework and .NET on Windows (i.e. using [DllImport]) only supports DLLs (Dynamically Linked Libraries), not statically-linked libraries.
You can also call into native code if the native code is available as a COM object, or can be accessed through platform features like OLE, WMIC, ADSI, etc (assuming your code's process is the same ISA as the native code you want to call, as it will still be loaded into your process, which is why you can't use 64-bit Office Excel to open databases where only a 32-bit OLE-DB or ODBC driver is available).
When a library is available as a *.lib then you need to make your own native host first - a simple C/C++ Win32 (PE) EXE or DLL that re-exports all of the useful functions from that *.lib will be sufficient - because then those exports can be imported by C#/.NET.
But in general:
If you are exporting COM objects to .NET then you don't need both the source-code files (*.c, *.cpp) or header files (*.h and *.hpp), only the IDL files or *.tlb (Type-lib) which the compiler will generate for you.
If your native code is also available through other platform features like OLE, ActiveX, COM Automation (IDispatch), ODBC, OLE-DB, ADSI, WMI, etc then you wouldn't be using [DllImport], and those platforms all either provide a standard interface (like ODBC and OLE-DB)
But generally speaking, no - you do not need the source-code (i.e. both *.c and *.h files) to create a .NET wrapper around native code exported from a native DLL and imported into .NET using [DllImport].
But you will need the header files (*.h) from a C/C++ project in addition to knowing the compiler settings (for finding out things like calling-convention, parameter marshaling info, etc) and a PE inspector (to verify the exported functions are at least present in the DLL you want to load).
Don't forget to ensure you provide both x86 and x64 native DLLs for all functionality if you're compiling your C#/.NET code for AnyCPU (tip: Using a 32bit or 64bit dll in C# DllImport )
so I'm going to be making a gmod module to async a few tasks and generally make the server run better and faster.
I want to make this in c# (so I don't have to write up a large cross-platform wrapper, and it doesn't take hours to write what 20 minutes can do in c#) but I don't know any cross-platform library that supports native loading and native exports. I know that DllExport works but only for windows .Net Framework and not Linux or even just dotnet core without a custom coreclr.
[DllExport("gmod13_close", CallingConvention = CallingConvention.Cdecl)]
public static Int32 Close(IntPtr LuaBasePtr)
{
return 0;
}
[DllExport("gmod13_open", CallingConvention = CallingConvention.Cdecl)]
public static Int32 Open(lua_State LuaState)
{
return 0;
}
if it is not possible to enable it to be loaded by dlopen directly without some workaround, what's the workaround I can get by just using that.
You cannot write a C-compatible shared library directly in .NET on a Unix system. C#, like other .NET languages, is managed code: it has a garbage collector and an interpreted runtime. In order to write a dynamically loadable module usable on Linux, you'd need to write in a language that compiles to machine code (e.g., C, C++, or Rust) or use wrapper code that starts the .NET runtime and invokes the function you want to call. This may happen to work on Windows due to COM, but it won't on Unix or Linux.
For similar reasons, it isn't possible to do this with Java, either, unless you're using something like GCJ that compiles to native code.
In general, .NET is not a good environment if you're trying to target Linux systems because it isn't designed to work well there (it does work, but it integrates poorly) and different distros include different runtimes (Mono vs. .NET Core). Users are also not likely to have it installed and therefore it generally adds a large (and often undesired) dependency to your software.
If you really want to do this, there is example code for doing something like this in the CoreCLR tree. Note that this depends on .NET Core, so it won't work on Mono, and therefore won't work on Debian or Ubuntu without additional software.
I understand that aim of the .NET core is for cross platform development, but I am looking for backward compatibility. If I have a linux library available (maybe, legacy) and I want its functions to be called from .NET core application for linux platform. Is it possible?
I am not talking about ASP.NET core, I need it for a desktop application.
Yes: https://github.com/dotnet/corefx/issues/343
That being said, I'll admit to not having actually tried it yet. I have used this a far bit on Mono, for what it's worth, and it's definitely worth reading their documentation on this: http://www.mono-project.com/docs/advanced/pinvoke/ ... because .net core seems to take much the same approach (eg: leave off the file extension for the p-invoked library, so the system can take care of linking to the right version etc...)
Eg how bits of .net core itself do this:
const string LIBC = "libc";
[DllImport(LIBC, EntryPoint = "getenv")]
private static extern IntPtr getenv_core(string name);
https://github.com/dotnet/corefx/blob/79d44f202e4b6d000ca6c6885a24549a55db38f1/src/System.Console/src/Interop/Interop.manual.Unix.cs
Look at SWIG. It is a simple way to wrap a shared library and it generates all of the P/Invoke code for you as well as maps any header files (think structs) between your .so library and your C# code. We created a simple cpp wrapper around the .so library that we wanted to use and then let SWIG do its magic. We now have a C# library that can call from our .Net code (a simple console app) that invokes our linux library functions. We have done this on a PI, on unix hosts running Ubuntu, CentOS, and Debian with great success. http://www.swig.org/
I am new to using .NET, but I am interested in using MonoTouch/Droid to write mobile applications that could share some core code.
I have many C style API libraries I wish to use, for example libxml2. How do I call these native library methods in Mono? Can I use the same binaries compiled from Windows if I am developing in Windows? Can I use the Windows binaries if I am developing in OS X?
How do I call these native library methods in Mono?
You use p/invoke (platform invoke) to call native C code from any .NET language. You need to write those declarations (of find someone who did it before you) to use the native libraries. Like #Marcelo commented there are often very good, much easier to use .NET alternatives to most C libraries.
This will work on MonoTouch too. However you'll need provide a static library (.a on OSX, like a .lib on Windows) since Apple iOS does not allow linking with user-provided dynamic libraries (.dylib on OSX/iOS and .dll on Windows).
Can I use the same binaries compiled from Windows if I am developing in Windows?
Windows produced binaries should run fine with Mono on Windows. You can use Microsoft .NET on Windows too.
Can I use the Windows binaries if I am developing in OS X?
If the binaries are .NET compiled code then yes - as long as your p/invoke declrations are portable (e.g. 32 vs 64 bits types).
If the binaries are native code then no. Remember that Mono is not a Windows emulator. It runs CIL code, inside .EXE or .DLL, but it won't run native Windows code or provide access to Windows native API (outside Windows).
Ahead of Time Compilation or AOT is a feature of the Mono runtime code generator.
mono --aot program.exe
This will generate a file called "program.exe.so"
How can i load this shared object file in php script and access the class objects and methods. ?
Thanks
The native library still needs to be loaded inside an AppDomain (i.e. the Mono VM/runtime) in order to run, it is not a native library as such.
If you must I'd suggest looking at
whether php supports COM interop (I don't use php, but I'd reckon the chance exists). This would be good since you could use that and profit from OO interface exposure
Use Swig which has support for C# some time now
Alternatively, use mkbundle, and/or create a native shared library that embeds a Mono VM. The shared library wrrap around the C# interface using a "C" native API's.
The Phalanger project should be able to do this. You can compile your php code with mono and also integrate with .net from php.