P/Invoke Runtime Errors - c#

I am trying to create a managed wrapper around a C++ dll. When I try to run a test app, I get an error saying loading the dll failed. This turns out to be a problem with trying to find the CRT. Copying the CRT to the same directory moves past this problem, but then throws an error saying the application loaded the C Runtime incorrectly (R6034). A native C++ program has no trouble with either of these issues.
The dll was compiled with vc 2008 - the managed code is compiled in 2010.
The dll has a manifest and I have tried copying the exact version of the CRT into the working directory with the same result as above.
My questions are :
Why can the native program load the CRT, but the managed wrapper can't find it?
Where could I look for things to try to fix the second error about loading the CRT?
Could this be because of name mangling, CallingConvention, etc?
C++ Code (I only have the header):
class Foo {
public:
static void startCall(std::string hostname);
}
C# Code:
[DllImport("mydll.dll")]
public static extern void startCall(string hostname );
public Test()
{
string hostname = "";
startCall(hostname);
}

As far as I know it is impossible to have STL in function interfaces if you want to use the functions in C#.
If you can change the C++ library interface, change it to use char* instead of strings. If you can't write a proxy library which exposes the interface with char* and converts it to std::string and then calls the c++ library which has functions with std::string

Related

C# based DLL wrapping C based DLL Usage Problem

I have code written in ANSI C that I would like to use in C#. I have compiled the C code into a DLL and created C# wrapper classes to interop with the C code. The point of the wrapper is to simplify a users interaction with the underlying C code.
[DllImport(DLL, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern void PrintHelloWorld();
public void PrintHelloWorldC()
{
PrintHelloWorld();
}
Above is a simplified example of what I have done so far. Now, I am trying to create a DLL from the C# wrapper classes I wrote. From here I could give both the DLLs created and someone would be able to interact with the C# based DLL to interact with the underlying C based DLL. Below is what I have done and what problem I am having.
I compile the C code into a DLL in Visual Studio 2019 with my Configuration=Release and Platform=Win32.
I compile my C# classes into a DLL in Visual Studio 2019 with my
Configuration=Release, Platform=Win32, and Platform Target as x86.
I create a new project and link my C# DLL and set Platform Target as x86.
I put my C DLL into the Debug folder of the project so that it is available to the C# DLL through the marshal directive.
I try to make a call into the C# DLL and below are the chain of events occurring.
Program calls C# DLL method PrintHelloWorldC() and is successful
Within PrintHelloWorldC() it tries to make a call to PrintHelloWorld();.
Following Error Occurs:
System.BadImageFormatException
HResult=0x8007000B
Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
My research yielded that it was most likely a mismatch in Platform Target between the DLLs and Test Project, however, I have double checked all the configurations and they should all be compiled for x86.
Below is what additional testing I have done.
Created a C# Project, and wrote simple code to make a call directly into the C based DLL. This works fine.
It seems that as soon as I try to use the two DLLs on top of each other in another project I start facing issues.
Any help or guidance is appreciated. Thanks in advance!

How can a C# program use a C++ dll of any version?

We're creating a dll, written in C++, providing access to some hardware. We also have a C# program that uses this dll.
We're having an issue with the versions. Indeed, when running the C# program, it absolutely wants to use the exact C++ dll version it used when compiling. I.e. if the C# program was compiled using C++ dll 1.2.3.4, then the program will refuse to run with C++ dll 1.2.3.5.
I'd like to instruct the C# program to use any C++ dll with version 1.2.anything.
Where can I configure this in the C# project?
This question has been superseded by that one, more related to COM.
Nothing this fancy exists in C++. Using a side-by-side manifest technically permits this but you would have known about it since you would have typed the version number in the manifest of your C# program.
The far more likely explanation is that you actually created a C++/CLI assembly. Many programmers confuse C++/CLI with C++. Easy mistake since that language permits using native C++ code. But it actually gets compiled to a mixed-mode assembly, an assembly that contains both IL and native code. The normal CLR version checking occurs for such an assembly when the CLR loads it, it is only happy with an exact version match. A strong DLL Hell counter-measure.
And the normal CLR version wrangling option is available to bypass this check, a <bindingRedirect> element in your app.exe.config file. As well as controlling the assembly version number the way you do it for your C# code so this isn't necessary.
The easiest way to check if this guess is accurate is by using Project + Add Reference and select the DLL. If that doesn't draw any complaint and the assembly gets added to the References node of your C# project then you know it is a normal .NET assembly. Don't forget to take advantage of that, no pinvoke required.
Load the dll at runtime and use reflection to call it's methods.
Assembly assembly = Assembly.LoadFrom("C:\\test.dll");
Assembly.GetTypes();
Activator.CreateInstance(type);
I don't think it is possible to configure your program to use 1.2.* version and no others. Unless you would write the code for that on your own. Another possibility would be not to change the version tag of the C++ dll, but it does not seem you want to that.
A solution avoiding the version dependency would be the usage of dllimport. You can load any dll written in C++ with it. It is free of version dependency. See the example from the msdn and link at the end:
using System;
using System.Runtime.InteropServices;
class Example
{
// Use DllImport to import the Win32 MessageBox function.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
static void Main()
{
// Call the MessageBox function using platform invoke.
MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
}
}
Description in MSDN

Error LNK2028: Thrown when instantiating an native C++ class within C++/CLI

Currently I'm working on a solution that contains a C++/CLI project (which is a wrapper of a native C++ dll) and a C# WPF project (which uses the functionality of the C++/CLI wrapper).
The problem I have is that when a pointer to a native class is instantiated (within the wrapper) a linker error occurs.
Class:
public ref class MCBiosUpdate
{
public:
MCBiosUpdate(void);
MCBiosUpdate(MCBiosUpdate^);
MCBiosUpdate(CBIOSUpdate&);
~MCBiosUpdate(void);
!MCBiosUpdate(void);
private:
CBIOSUpdate *pBiosUpdate; //Native C++ Class
};
Code that causes error:
MCBiosUpdate::MCBiosUpdate(void) : pBiosUpdate(new CBIOSUpdate) //error LNK2028
{
}
Output:
1>MCBiosUpdate.obj : error LNK2028: unresolved token (0A00000E)
"public: __thiscall CBIOSUpdate::~CBIOSUpdate(void)"
(??1CBIOSUpdate##$$FQAE#XZ)
How can I resolve the linker error so that the program runs as intended?
What causes this linker error?
If there is any improvements to the code or any suggestions to help me resolve the problem; feel free to comment.
What causes this linker error?
Reason could be pBiosUpdate interface is not exported from the DLL to be visible to the DLL'S clients, in your case the C# code.
How can I resolve the linker error so that the program runs as intended?
use dllexport as mentioned here
(or)
Use a module definition file (.def file) to export the DLL's function as mentioned here

How to use a C++ dll in Unity3D?

I am aware of this similar question, but it does not respond to my problem.
I have written two .dlls using Visual Studio 2010. One is in C++, and communicates with an SDK that was written in C++. The other is a C# wrapper for that C++ library, so that it can be used in C# contexts.
My plan was that this would let me use my code in Unity3D, but apparently that is not the case. It seems like Unity3D does not allow me to import .dlls as Assets if they are not a .NET assembly. So I can add my C# wrapper, but not the C++ dll.
This results in a DllNotFoundException whenever I try to access the C++ library. I have tried simply copying the C++ library into the Assets/Plugins folder, but that gives the same results.
Is there a way to do this properly? This is a very vital part of my project setup.
The problem is that the DLL is not being found when the p/invoke runtime code calls LoadLibrary(YourNativeDllName).
You could resolve this by making sure that your DLL is on the DLL search path at the point where the first p/invoke call to it is made. For example by calling SetDllDirectory.
The solution that I personally prefer is for your managed code to p/invoke a call to LoadLibrary passing the full absolute path to the native DLL. That way when the subsequent p/invoke induced call to LoadLibrary(YourNativeDllName) is make, your native DLL is already in the process and so will be used.
internal static class NativeMethods
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr LoadLibrary(
string lpFileName
);
}
And then somewhere in your code:
private static IntPtr lib;
....
public static void LoadNativeDll(string FileName)
{
if (lib != IntPtr.Zero)
{
return;
}
lib = NativeMethods.LoadLibrary(FileName);
if (lib == IntPtr.Zero)
{
throw new Win32Exception();
}
}
Just make sure that you call LoadNativeDll passing the full path to the native library, before you call any of the p/invokes to that native library.
Note that the DllNotFoundException can be caused by building your Unity DLL in Debug instead of Release!
A simple oversight that can cause a headache.
This also happens when Unity can find your DLL, but is not able to find it's dependencies. Obvious fix is to place dependency DLLs into /Plugins as well, or link your dependencies statically.
Less obvious reason is when your DLL depends on Visual Studio runtime library dynamically, i.e. is built with Properties -> C/C++ -> Code Generation -> /MD option. Change it to /MT to link with runtime statically.

Calling C# from C

Has anyone worked on calling a C# module from C module. I tried searching on internet but didn't find good examples. Though lot of sites say something like using COM interop but couldn't find a proper example or article explaining it though.
If someone can help me on this, it would be great
Thanks,
Sveerap
There is more than just COM interop if you want to call into managed code from C or C++. The are also the following lesser known methods (taken from MSDN FAQ):
How do I call a .NET assembly from native Visual C++?
There are basically four methods to
call .NET assembly from native VC++ code:
CLR Hosting API: Native VC++ module calls CLR Hosting APIs to host CLR, load and call the .NET assembly (sample code: CppHostCLR).
COM Interop: If the .NET assembly can be exposed as a COM component, native VC++ module can call into the .NET assembly through .NET – COM interop (sample code: CppCOMClient).
Reverse PInvoke: The managed code calls native code passing a delegate that the native code can call back (sample code: CSPInvokeDll).
C++/CLI: If the module containing native VC++ code is allowed to enable CLR, the native VC++ code can call
.NET assembly directly (sample code: Consuming C# Library in native C or C++ using C++/CLI)
Here is a solution. The solution allows calling a C# function from C by decorating your function with [DllExport] attribute (opposite of P/Invoke DllImport).
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
C# code
class Test
{
[DllExport("add", CallingConvention = CallingConvention.StdCall)]
public static int Add(int left, int right)
{
return left + right;
}
}
C code
int main()
{
int z = add(5,10);
printf("The solution is found!!! Z is %i",z);
return 0;
}
As #iceflow19 commented below:
The author of the link provides a CLR IL preprocessor as an added step during compilation. Since assemblies use the same binary container format (DLL) on windows, if you manually add the .Net functions offsets in IL to the vtable (the dll's list of exports), Windows is smart enough to invoke the CLR to run that code when called from C. However there is overhead. It's an unadvertised feature. This is how mixed managed libraries in C++/CLI work. To use it just add it through Nuget. The extra target added in your MSBuild project file will provide for the IL preprocessing step
You could expose your C# module as COM:
http://www.codeproject.com/KB/cs/ManagedCOM.aspx
Best method of calling managed code(c#) from unmanaged C++
http://www.codeproject.com/KB/COM/cominterop.aspx
There is also the option of building native libraries from C# code using CoreRT and call them from C.
Here is an example.
Edit: CoreRT has moved to runtimelab feature NativeAOT. Updated link.

Categories

Resources