Can you link a .so in dotnet? - linux

I have a .NET core project that uses a .so file. I use [DllImport()] to import it. My problem is that this .so has a dependency libtomcrypt.so so it can not locate some symbols(undefined symbol: cipher_descriptor).
I tried importing my .so in C and it works fine if I specify the linker variable -ltomcrypt.
Adding a reference to libtomcrypt.so in the .NET core project did not help because it is a native .so.
Is there any way to link libtomcrypt.so to dotnet?

Try to load your library with NativeLibrary first.
static class Library
{
const string MyLibrary = "mylibrary";
static Library()
{
NativeLibrary.SetDllImportResolver(typeof(Library).Assembly, ImportResolver);
}
private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
IntPtr libHandle = IntPtr.Zero;
if (libraryName == MyLibrary)
{
// Try using the system library 'libmylibrary.so.5'
NativeLibrary.TryLoad("libmylibrary.so.5", assembly, DllImportSearchPath.System32, out libHandle);
}
return libHandle;
}
[DllImport(MyLibrary)]
public static extern int foo();
}
Interacting with native libraries in .NET Core 3.0

Related

Expose types from embedded interop type to other assemblies

I have an ATL COM library that defines an enum and an interface in MIDL like:
[uuid(65785D49-574A-4B1B-95F1-B9C7F283364A)]
typedef enum Options
{
Option1,
Option2
} Options;
[
object,
uuid(2E3D1B1A-DF95-434F-836B-73FF1245B608),
oleautomation,
nonextensible,
pointer_default(unique)
]
interface IExample : IUnknown
{
HRESULT Test([in] Options option, [out, retval] BSTR* str);
};
I then create a managed assembly and reference the TLB, which creates a PIA and embeds the types (Embed Interop Types = true) into the managed assembly.
In the managed assembly, I now create a class that implements the interface:
public class Example : IExample
{
public string Test(Options option)
{
return option.ToString();
}
}
Now I would like to create a third assembly that references the managed assembly and creates the object and call into it, but it doesn't let me since Options is an unreferenced type (requires me to include the PIA generated from the typelib):
public class Equivalence
{
public void UseTest()
{
Example e = new Example();
e.Test(Options.Option1); // recognizes that it requires an ExampleLib.Options parameter, but that type isn't available
}
}
Using reflector, I can see it inside the managed assembly, but it isn't viewable by object browser:
namespace ExampleLib
{
[ComImport, CompilerGenerated, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("2E3D1B1A-DF95-434F-836B-73FF1245B608"), TypeIdentifier]
public interface IExample
[Guid("65785D49-574A-4B1B-95F1-B9C7F283364A"), CompilerGenerated, TypeIdentifier("15a6cf97-c415-4866-bdfb-7da65edb1faa", "ExampleLib.Options")]
public enum Options
}
My managed assembly is itself a library intended to be distributed as an API, and I would like to expose this enumeration and interface so that it can be used by outside parties without having to deliver the PIA generated from the typelib of the ATL COM library. Is it possible?
Apparently this cannot be done. One of the errors (CS1748) pointed me to this post which says the PIA must be linked in by both assemblies.

VSIX Extension uses 3rd party DLLs unable to load one of the dependency

I am developing an extension to VS2013. Since it will be installed through MSI, I am changing the base directory to installation folder using ProvideBindingPath attribute to package class. But the 3rd party dll reference which will be loaded in runtime is not picking dll from the probed path. Its always looking into Visual studio devenv.exe folder. Is there any way to force the dll to look into my installation folder.
using MD=Microsoft.VisualStudio.Modeling.Shell;
MD.ProvideBindingPath(SubPath = #"")]
public sealed class AutomationCommandPanePackage : Package
{
public AutomationCommandPanePackage()
{
string installationPath = HelperMethods.GetInstallationPath();
if (string.IsNullOrEmpty(HelperMethods.GetInstallationPath())) return;
// Change default config file at runtime.
using (AutomationConfigurationManager.Change(installationPath, "AutomationPro.config"))
{
// Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
Assembly a = Assembly.GetExecutingAssembly();
Type type = a.GetType("AutomationCommandPanePackage", true);
System.Reflection.MemberInfo info = type;
var attributes = info.GetCustomAttributes(true);
foreach (var attrib in attributes)
{
if (attrib is MD.ProvideBindingPathAttribute)
{
((MD.ProvideBindingPathAttribute)attrib).SubPath = installationPath;
break;
}
}
I have been able to successfully load third party (telerik) assemblies in my extension using below code.
Register to AssemblyResolve event in your Package class constructor
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
Then in handler load packages as below:
string path = Assembly.GetExecutingAssembly().Location;
path = Path.GetDirectoryName(path);
if (args.Name.ToLower().Contains("telerik.windows.controls.gridview"))
{
path = Path.Combine(path, "telerik.windows.controls.gridview.dll");
Assembly ret = Assembly.LoadFrom(path);
return ret;
}
I have not had any issues with the above approach.
I resolved issue using
LoadLibrary() from
System.Runtime.InteropServices;
since my dll to be loaded is a COM iterop dll.
public static class win32
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
in package.cs I loaded assembly like this
win32.LoadLibrary(Path.Combine(installationPath, "apidsp_windows.dll"));

Get assembly version in PCL

I have the following line of code in .NET 4.5 that I am trying to build as Portable Class Library. It's purpose is to get assembly version:
this.GetType().Assembly.GetName().Version.Major;
The problem is that Assembly.GetName() is not available in PCL. Is there a way to get assembly version in PCL?
I know it is possible to parse Assembly.FullName, but I want a better solution.
public static string Version
{
get
{
var assembly = typeof(MyType).GetTypeInfo().Assembly;
// In some PCL profiles the above line is: var assembly = typeof(MyType).Assembly;
var assemblyName = new AssemblyName(assembly.FullName);
return assemblyName.Version.Major + "." + assemblyName.Version.Minor;
}
}
I now use the following:
[assembly: AssemblyTitle(AssemblyInfo.AssemblyTitle)]
[assembly: AssemblyProduct(AssemblyInfo.AssemblyProduct)]
[assembly: AssemblyVersion(AssemblyInfo.AssemblyVersion)]
[assembly: AssemblyFileVersion(AssemblyInfo.AssemblyFileVersion)]
[assembly: AssemblyInformationalVersion(AssemblyInfo.AssemblyInformationalVersion)]
internal class AssemblyInfo
{
public const string AssemblyTitle = "...";
public const string AssemblyProduct = "...";
public const string AssemblyVersion = "1.0.0.0";
public const string AssemblyFileVersion = "1.0.0.0";
public const string AssemblyInformationalVersion = "1.0.0.0-dev";
}
This allows me to reference any of the constants within the assembly without using reflection, e.g. AssemblyInfo.AssemblyProduct.
You are targeting a Silverlight-based platform (Silverlight 4 or higher, Windows Phone before version 8). Those platforms didnt' support the GetName() method. For those platforms, you can define an extension method like this:
public static class AssemblyExtensions
{
public static AssemblyName GetName(this Assembly assembly)
{
return new AssemblyName(assembly.FullName);
}
}

Visual C++ static library

I am writing a c++ static library A.lib in visual studio 2008. In my static library, I am using few APIs exposed by another static library B.lib(.lib).
I have a written an application that uses A.lib. Since few header files in A.lib are using headers from B.lib, my application wants a path of B.lib header files. How can I avoid my application so that I need not to provide path of B.lib header files for compilation ?
Refrain from using types from B-headers in the interface of your library. A good way of totally hiding the implementation is using the factory-pattern along with pure abstract base classes as interfaces. You will still have to link B.lib in your application though.
Sample Before:
// A.h
#include "B.h"
class Foo {
public:
void DoStuff();
private:
B::Bar Data; // B::Data comes from library B
};
This in your header adds a dependency to B.
With Factory, your application now uses IFoo.h instead of A.h:
// IFoo.h
class IFoo {
public:
static IFoo * CreateInstance( ); // implemented in IFoo.cpp, just returns new Foo
virtual void DoStuff() = 0;
virtual ~IFoo() {}
};
// A.h
class Foo : public IFoo {
public:
virtual void DoStuff();
private:
B::Bar Data; // B::Data comes from library B
};
You can go to settings and add the directory to the additional include directory's and you can just use the header by name.

Compile Using MONO - C# with Reference To A C# Library?

I have a C# library (DLL)
// ProgramLib.cs //
using System;
namespace ProgramLibrary
{
public class Lib
{
public Lib()
{
Console.WriteLine("Lib Created");
}
}
}
And I have the following console program
// Program.cs //
using System;
using ProgramLibrary;
class MainClass
{
public static void Main (string[] args)
{
ProgramLibrary.Lib lib = new ProgramLibrary.Lib();
}
}
In a linux environment, if both files reside in the same directory
What is the Mono compiler (mcs) command that compiles Program.cs with reference to ProgramLib.cs?
Thanks all!!
First compile ProgramLib to ProgramLib.dll, then reference it:
$ gmcs -t:library ProgramLib.cs
$ gmcs -r:ProgramLib.dll Program.cs

Resources