How to call c++ unmanaged code in C# wrapper? - c#

I have C# wrapper project that uses C++ unmanaged dll code with help of [DllImport] attribute and static extern methods. This is the preferred method described by MSDN.
The problem is that we can have only one of the c++ runner, which means we can't run tasks in parallel.
How to call the unmanaged C++ without using the dllimport + static extern methods so that when we instantiate one of the c# objects it instantiates a new c++ dll object
This is how we are calling C++ code right now.
public class FMU : IDisposable
{
[DllImport("FMU.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
private static extern IntPtr Load(string fmuFileName, bool isCoSimulation, AddMessageDelegate messageDelegate, int arrayLocation);
[DllImport("FMU.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Instantiate(IntPtr fmu, bool isCoSimulation, bool loggingOn, int nCategories, string[] categories);
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);

Related

C# Windows Forms Unable to load unmanaged C++ DLL on Windows10

I have a C# Windows Forms Application that use an unmanned c++ dll.
When when I debug, or run it as standalone (on windows7), I just put the dll next to the app exe and it runs great.
When I try to do the same on Windows10 (run as standalone) I get the following exception:
Unable to load DLL 'AnalyzerLib.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Can anyone tell me why? should I give a permission somewhere or register it?
Here is how I access the dll from code:
namespace Analyzer {
public unsafe class Connector {
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool isAvailable();
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern void win32set_DetectParams(float[] parameters, int prob_Size);
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern void win32setDetectParamsAndColorMatrix(float[] parameters, int prob_Size, float[] colorMatrix16bytes);
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern void win32analyzeBuffer(byte[] javaBuffer, byte[] javaInputCopyBuffer, int[] analyzeBufferResArr, int width, int height, bool convertYUV2RGB);
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int getCoreLogBufferSize();
[DllImport("AnalyzerLib.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
private static extern byte* getCoreLogBuffer();
}
}
If the DLL you are loading is in the same directory as the executable, then it will be found. Which leads us to conclude that the module(s) that cannot be found are your DLL's dependencies.
Normally this means that you need to install the appropriate MSVC runtime upon which your DLL depends.
Make sure the you run the release version and not the debug
You can figure out the dll dependencies by running from command prompted:
dumpbin /DEPENDENTS my.dll

DLLImport fails to find the DLL file

I have a C# application which needs to import a function from a C++ dll. I use DLLImport to load the function. It works fine in English and Chinese environment, but it always raise 'Module not found' exception in French operating system.
The code snapshot:
[DllImport("abcdef.dll", CallingConvention = CallingConvention.StdCall)]
public static extern string Version();
Note that letters in the name of module have been replaced but the name itself is in the same format and the same length.
And a screenshot:
Any ideas?
I have tried all methods you proposed, however the problem still exists.
Here is an alternative way which could avoid that error. It uses Win32 APIs to load the library and find the address of the function, then invoke it. Demo code follows:
class Caller
{
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
private IntPtr _hModule;
public Caller(string dllFile)
{
_hModule = LoadLibrary(dllFile);
}
~Caller()
{
FreeLibrary(_hModule);
}
delegate string VersionFun();
int main()
{
Caller caller = new Caller("abcdef.dll");
IntPtr hFun = GetProcAddress(_hModule, "Version");
VersionFun fun = Marshal.GetDelegateForFunctionPointer(hFun, typeof(VersionFun)) as VersionFun;
Console.WriteLine(fun());
return 0;
}
}

Why do I need to define DLLImport with EntryPoint attribute

While going through SWig generated wrappers, I find that the PInvokes don't have any entry point defined, but some places do have an entry point. So what is the difference between them? When do I need to define an EntryPoint, and when do I not need to?
Defined without EntryPoint:
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
public static extern bool ReadFile(
HandleRef hndRef,
StringBuilder buffer,
int numberOfBytesToRead,
out int numberOfBytesRead,
int flag);
Defined with Entrypoint:
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFile")]
public static extern bool ReadFile2(
HandleRef hndRef,
StringBuilder buffer,
int numberOfBytesToRead,
out int numberOfBytesRead,
Overlapped2 flag);
Also why does the function have to be static as in public static extern? I assume that extern is telling the compiler that this method is defined externally?
The EntryPoint field serves to tell the .NET runtime which function to call from the DLL being invoked; if it's not set, the default is the same name that the .NET method declaration has. In your second example, omitting EntryPoint = "ReadFile" would result in the runtime trying to call a function named ReadFile2 (which does not exist).
The prototype needs to have the static and extern modifiers because the specification says so. It does not need to be public; controlling the visibility of the method is entirely up to you.

P/Invoke from C#: Call functions of returned object

I have a native/unmanaged DLL and it has a "CreateObject" function which returns a pointer to the business object.. so the call would be sth. like:
[DllImport("MyDll.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateObject();
Question:
The object is exposing public-functions like "Connect()" which i want to call, but i don't know how to "map" these calls so i have a simple method-signature like:
private bool Connect();
Any ideas?
The way to do this is to provide another PInvoke function which calls into a C function that does the method call
[DllImport("MyDll.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool Connect(IntPtr businessObject);
Then in C you define the following
extern "C" {
bool Connect(Business* pObject) {
return pObject->Connect();
}
}
You have to wrap the C++ objects up in free functions:
bool Connect(MyObject* obj)
{
return obj->Connect();
}
and then export these from your DLL.
Alternatively you can make use of the fact that you are compiling with C++/CLI and export a managed C++/CLI class which can be consumed directly by your C# code.

Create an API in C# which can be called from it's DLL

I know the title is bit confusing for my question.
Let me explain:-
There are some DLLs written by my seniors and I use them in C# as follows:
Say, Existing DLL name is SeniorDLL and I want to use function SeniorFunc from that DLL.
What I do is:-
private delegate int SeniorFunc(IntPtr Blah);
[DllImport("kernel32")]
public extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
SeniorFunc fp_Senior;
and in function where I want to use this function, Before first function call I write:
IntPtr handle;
handle = IntPtr.Zero;
handle = LoadLibrary("<DLL Path>");
IntPtr fPtr = GetProcAddress(handle, "SeniorFunc");
fp_Senior = (SeniorFunc)Marshal.GetDelegateForFunctionPointer(fPtr, typeof(SeniorFunc));
and then I use this function via fp_Senior(<Parameter>);
Now I want to create such DLL for me in C# by which I'll be able to call functions from DLL.
Currently I created a DLL but I have create an instance of class in DLL and then have to access like ClassInstance.MyFunction(<Parameters>);
How can I get directly function calls without creating an instance?
In other words, (I don't know I am correct or wrong) How can I create APIs??
Thanks!!
You don't need an instance here, everything can be static. Something like this, with the necessary error checking added:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
internal static class NativeMethods {
public static void SeniorFunc(IntPtr arg) {
if (fp_Senior == null) lookUpSenior();
fp_Senior(arg);
}
private static void lookUpSenior() {
loadSenior();
IntPtr addr = GetProcAddress(SeniorModule, "seniorfunc");
if (addr == IntPtr.Zero) throw new Win32Exception();
fp_Senior = (SeniorFuncDelegate)Marshal.GetDelegateForFunctionPointer(addr, typeof(SeniorFuncDelegate));
}
private static void loadSenior() {
if (SeniorModule == IntPtr.Zero) {
SeniorModule = LoadLibrary("mumble.dll");
if (SeniorModule == IntPtr.Zero) throw new Win32Exception();
}
}
private static IntPtr SeniorModule;
private delegate int SeniorFuncDelegate(IntPtr Blah);
private static SeniorFuncDelegate fp_Senior;
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
}
The point of keeping lookupSenior in a separate method is to allow SeniorFunc() to get inlined so it is fast. If you know you'll always use these functions in your program then you can also write a static constructor for the class and do the lookup there. Saves the null check but makes an exception a bit harder to interpret.
There is no such a thing as a method outside a class in C#. So if you must call a method, you have to specify the class name.
The difference with the DLLs you are currently using is that those DLLs are written in C/C++ or other non-.NET language which does not enforce a strict object-oriented approach like C# does.
Thus, nothing forces you to create an instance of a class when calling a method from a .NET library. If a method is declared as static, you can call it directly through ClassName.MethodName().

Categories

Resources