How to create a C# DLL for Xamarin.Android from C++ - c#

I have an iPad application written in C# using Xamarin.IOS, that uses some C++ code which has been built into a C# DLL following the instructions here.
I am now wanting to add an Android version of my application, so I need to build a version of this DLL that will be compatible.
For the Xamarin.IOS version, the process is essentially:
The C++ code is compiled with XCode to make a lib.a file
SWIG is used to generate some C# interface files from the C++ header files
XCode builds a libWrapper.a file from one of the files SWIG generates
SMCS (seems to be a Xamarin tool command line tool) combines the lib.a, libWrapper.a and an AssemblyInfo.cs file into a C# dll, which can be added as a reference to the iPad project.
Using the DLL already generated in the Xamarin.Android project doesn't work (it gives a P/Invoke EntryPointNotFound error), presumably because it is built for iOS devices (i386, arm7 and arm7s) and it needs to be built differently for Android?
I think I need to use the Android NDK to compile the C++ (as opposed to XCode), but what would that produce and how do I convert it into a C# DLL in order to add it to my Xamarin.Android project?

Android NDK will produce a .so file. You can use the same PInvoke methods as in your iOS wrapper. I have used SWIG with Android before so there should not be any difference since it's a C interface.
Add the .so file to a library project and set it to build as EmbeddedNativeLibrary.
http://developer.xamarin.com/guides/android/advanced_topics/using_native_libraries/

Related

How to link a .so file to a managed DLL with mono

I'm writing a program for embedded linux on an ARM processor in .net that uses mono to execute. I have found that I can simply compile to either x86 or x64 architecture on my PC, copy the Debug directory over to linux, and run the program using mono myProgram.exe. The program is working perfectly like this and mono seems to take care of the architecture mismatch. This was true until today when I tried to incorporate an external native DLL.
I have both an x86 and x64 bit architecture of the external DLL and both work on the desktop environment fine. I have a shim class that uses [DllImport] to load the extern functions. However, when I try this on embedded linux with Mono I am getting a BadImageFormat exception. My guess is that Mono somehow transitions the compiled DLLs in the exe at start up but doesn't do the same for the external.
Some other info:
1. I don't have source for the native external library. I have x86, x64, and a .so library.
2. I have tried making a manage C++ shim that accesses the .so but can't get it to compile on the desktop since windows doesn't recognize the .so file.
Some thoughts:
1. Is there a way to embed the native DLL into a managed so that Mono will transition the native DLL too?
2. Can I link the .so file to a managed C++ project?
3. Is there a way to tell Mono to incorporate that Dll during execution?
Ultimately I'm looking for a solution that is wrapped in the exe that allows me to simply run it like I did before and control the native system.
If you have all the .dll and .so files for Windows and Linux, you can probably use dll maps feature of Mono. (https://www.mono-project.com/docs/advanced/pinvoke/dllmap/) which are used to map Windows dll names to Linux so names.
.Net does not recognize this, but Mono does.

Using a C# class from a managed C++ project

I have a solution with a managed C++ project and a C# project. The C# project is a class library project containing the GUI classes I use from the C++ project. This works well, but building results in two DLLs.
Is there a way of using the C# objects from the C++ project without having a dynamically linked library generated by the C# project (is there a way to embed the C# types into the managed C++ project)?
I am using Visual Studio 2015.
There is a way, but it is far outside the tooling you are using to be able to accomplish it.
You can use command line tooling to create a multi netmodule assembly.
Managed assemblies are built of one or more "netmodules". Typically in a C# project, there is only one netmodule, and the C# compiler builds it and then links it into the assembly it produces. By using the command line tools, you can build only a module, then link it with the C++ module into an assembly.

Native C++ dll in one solution with C# project

I have a source file written in C++, performing some simulation. I would like to create a user interface for this in C#. How can I have both C++ and C# in a single Visual Studio solution?
What I did so far was I created a .NET C# project and solution, and then a native project as a DLL library. I have marked the C# project as "Depends on" the C++ dll. I have provided the necessary dllexport directives and imported using DllImport. Everything compiles fine, but when I execute the application, the dll is not found:
Unable to load DLL 'xxxx.dll': The specified module could not be found.
It is no surprise the DLL is not found, as the application is run from its output directory and the output directories are different for the C# and C++ projects. I do not want to write an explicit path as my import like `"..\..\Debug\xxxxx.dll".
Is there some common way how to structure a solution containing native a Dll and C# app so that the C# app can call the native Dll?
If you know that after deployment your C++ DLL will be in the same folder as your C# DLL (or executable), then on simple way to solve the problem is to use the PostBuild event (Project properties, Build events).
You can add a copy command that will put your C++ DLL into the C# output folder.
I found a very comfortable way, which might have some unexpected drawbacks, but I do not see any so far: I can enable CLR for the C++ DLL project, making it "mixed", even if it in fact does not contain any managed code, and then the project building it can be made a Reference in the C# .NET project.
To make the project mixed mode set Configuration Properties / General / Common Language Runtime Support to Common Language Runtime Support (/clr).
After this the build system copies the DLL into the application output folder automatically.

Trying to link C++ library with C# using swig - will not let me add reference to resulging dll to C# project

I'm trying to make c# bindings for a library. I used cmake to create a visual studio 2010 solution from the library source, and that compiled fine. I used the included .i file to create the wrappers as per the instructions here (https://code.google.com/p/labstreaminglayer/source/browse/LSL/liblsl-Generic/AUTOGENERATE%20HOWTO.txt ) using cygwin. I then added the resulting liblsl_warp.cxx file to the same project. It still compiled fine, so I would assume that the resulting .dll includes the required bindings.
I've added that project to my c# application and am trying to add a reference from the c# project to the resulting dll (also tried adding a reference to the project). The only error I get is A reference to 'lsl' could not be added..
What steps am I missing? I looked at a couple examples, and I am basically setup the same way, but their examples are significantly easier.
SWIG produces both C# and C++ source code. The C# code uses DllImport to import the functions from the C++ side - it doesn't use .net-like bindings. Therefore the C++ DLL does not need to be (and cannot be) registered, and hence can't be 'referenced'. Referencing is for registered DLLs.
So you have a C++ DLL and a C# exe. Just ensure the C++ DLL can be found by the exe, by putting it in the same folder for example. Don't worry about referencing it.

use vc++ class library in c#

i have created a simple "public ref class" in the vc++ project, which is configured to generate a dynamik library.
In the c# Project (simple console application) i added the vc++ project as to the References and doing a "using myVC++library".
But when i try to create an object from the vc++ dll i always get: System.BadImageFormatException was unhandled
any clues or helpfull tutorials on this?
TIA
Is your c# project set to build for "Any CPU" - if it is, and you're on a 64-bit OS, then the load will fail.
The VC++ dll will be 32-bit only, and 64-bit app can't run it.
You could change your c# build to target x86 instead.

Categories

Resources