C# : Referencing or using .so files in .NET Core on Linux
We finally figured out a way to do so but we are not sure it will be applicable to everybody and it might not solve somebody else's problem. Here goes our approach -
As mentioned in the question, the xprb.dll could not be loaded because libxprb.dll was what it was searching for in the Xpress lib directory (/opt/xpress/lib/). But after installing the Xpress in Linux, the installation contained only .so files and no .dll files.
There were some blogs which suggested using DllImport method to load the .so files and then call the methods. We didn't try those methods as we were looking for something simpler than that.
After investing the problem we found that only if we point the loading of shared libraries to somehow the installed .so files, it might work. So the situation was as such in our specific case -
- We did not have a libxprb.dll in the /opt/xpressmp/lib/ folder
- We had libxprb.so file instead of libxprb.dll in the /opt/xpressmp/lib/ folder (if we didn't have this file we probably wouldn't have known which other .so file to use)
So we created a symlink file libxprb.dll in /opt/xpressmp/lib/ folder (which we probably could have placed anywhere as long as it was in one of the path in LD_LIBRARY_PATH) which pointed to the libxprb.so file in /opt/xpressmp/lib/ folder using the command -
ln -s /opt/xpressmp/lib/libxprb.dll /opt/xpressmp/lib/libsprb.so
So now when xprb.dll was loaded, it looked for libxprb.dll which in turn pointed to libxprb.so file (as libsprb.dll was a symlink to libxprb.so) and hence xprb.dll was loaded successfully.
Calling UNIX and Linux shared object file .so from c#
Mono has the ability to integrate with native libraries from within C# built on top of dlopen(3). You just have to use the DllImport statement with the name of the library (i.e. 'libform.so.5'), then wrap the native code and data types with a friendly C# class that takes care of all the low-level stuff. This page has a good overview with lots of information on how to deal with marshaling pointers and other unsafe types.
Once you've got your wrapper class written, you can just use that without worrying about the fact that it's using a native shared library underneath.
How to correctly include and link a proprietary shared object library in C++
So i figured it out.
makefile
The only problem here is that i did not know how to use a glob pattern to include stuff automatically (like -Ilib/*/include
) but whatever.
CC := g++
SRC := wrapper.cpp
OBJ := wrapper.o
OUT := libWrapper.so
INCs := -Ilib/lib-name-api/include -Ilib/name-lib-module-A/include {etc. etc.}
LIB := -L/usr/local/lib/installedLibNameSos/ -lNameModuleA -lNameModuleB {etc. etc.}
all: $(OUT)
$(OUT): $(OBJ)
$(CC) $(OBJ) -shared -o $(OUT) $(LIB)
$(OBJ): $(SRC)
$(CC) -c $(SRC) -o $(OBJ) $(INCs) $(LIB)
wrapper.cpp
#include <stdio.h>
#include "NameApi.h"
// varius using namespace and other import stuff
extern "C" int test (){
return 42;
}
extern "C" string somethingReturningAString (){
// calls and stuff to the native library
return "Hi mom"
}
obviusly the .so needs to be copied where the executable is
csharpClass.cs
using System;
using System.Runtime.InteropServices;
// extension not needed.
// the library will be loaded along with the required .so's
// that have been linked from /usr/local/lib/installedLibNameSos/
[DllImport("libWrapper")]
extern static int test ();
[DllImport("libWrapper")]
extern static string somethingReturningAString ();
Console.WriteLine(test());
// 42
Console.WriteLine(somethingReturningAString());
// Hi mom
resources:
- Link .so file to .cpp file via g++ compiling
- Call C++ library in C#
- https://en.wikipedia.org/wiki/Platform_Invocation_Services (p/Invoke examples)
- https://learn.microsoft.com/en-us/dotnet/standard/native-interop/cross-platform
(note: the process works perfectly. But i've been using a library written and documented by a spastic monkey. So yeah i've literally learned the basics of g++, make and got crippling depression for nothing. lol)
Reference external DLL in .NET Core project
.Net Core 2 supports a direct reference to external .dll
(e.g. Net Standard libraries, classic .Net Framework libraries). You can do it through Visual Studio UI: right click on Dependencies->Add reference->Browse
and select your external .dll
.
Alternatively, you can edit .csproj
file:
<ItemGroup>
<Reference Include="MyAssembly">
<HintPath>path\to\MyAssembly.dll</HintPath>
</Reference>
</ItemGroup>
You can face with the following error:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly
then just remove \bin
folder an rebuild the project. It should fix the issue.
How it is possible
Net Core 2.0
supports .Net Standard 2.0
. Net Standard 2.0
provides a compatibility mode to connect .Net Core
(.Net Standard) and .NET Framework
. It can redirect references e.g. to System.Int32
from mscorlib.dll
(Net. Framework) to System.Runtime.dll
(Net. Core). But even if your net core app is successfully compiled with dependency on external dll
you may still have issues with compatibility during runtime if there is any API used by external library which .Net Standard doesn’t have.
How do I reference a .NET Framework project in a .NET Core project?
Yes, we are currently attempting the same thing. The trick is to make sure that you are supporting the same .NET frameworks. Inside your project.json file, make sure the framework matches the framework of the project you wish to include. For example:
"frameworks": {
"net46": { --This line here <<<<
"dependencies": {
"DomainModel": {
"target": "project"
},
"Models": {
"target": "project"
}
}
}
},
FYI: You might need to change the framework of your .NET Core or your older projects to achieve this. .NET Core can be changed just by editing the project.json file as seen above. You can so the same in .NET projects by right clicking the project and opening properties. Change the framework level there.
Once you have matched the two project frameworks then you should be able to include them. Good Luck!
Related Topics
Multiple Webrequest in Same Session
C# - Elegant Way of Partitioning a List
How Are Dlls Loaded by the Clr
Solving a Timeout Error for SQL Query
Multiple SQL Statements in One Roundtrip Using Dapper.Net
Get List of Certificates from the Certificate Store in C#
C# Winforms Application to Linux
Use Decimal Values as Attribute Params in C#
C# Async/Await Progress Event on Task<> Object
Signed VS. Unsigned Integers for Lengths/Counts
Is Tls 1.1 and Tls 1.2 Enabled by Default for .Net 4.5 and .Net 4.5.1
How to Ask The Socket to Wait for More Data to Come
Secure Way of Inserting Dynamic Values in External JavaScript Files