Calling C# (.NET) APIs from C - c#

To invoke a C API from C# I would use P/Invoke. But if I were to do the reverse, call .NET APIs from C, how would I go about it?

If you really want to do it all through C APIs and do an end run around COM and C++ you could do the following. But first figure out if it's truly necessary! I suspect in most cases it won't be.
Step 1. Create the C# .Net assembly you wish to call.
Step 2. Create a mixed mode CLI/C++ assembly with extern "C" functions exported. Have this assembly call the C$ assembly.
Step 3. Create your C application that calls the exported C style functions from the DLL made in step 2.
Things to consider.
A. Is there an actual NEED to have a C (versus C++/COM) app directly call a .Net assembly?
In other words, why not use C++ and COM to COM exported .Net methods if you really must have a mixed (.Net and non-.Net) application/system?
B. Will the APIs you write be wrappers on classes? If so, how will you manage their life times? (e.g. Will you create/use handles? How will you manage their relationships to the actual gc objects...etc)
C. Strings. These are handled very different between C and .Net. Make sure you're familiar with their differences and how to properly send strings across these boundaries...Hint: CString is your friend.

There is solution that can avoid using COM or C++\CLI. See here: Calling A .NET Managed Method from Native Code

you can turn c# code into COM, or use C++\CLI.

Here is a solution. It implements [DllExport] attribute
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
So one can do something like this to call managed code from unmanaged code:
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;
}

Related

Access C# static class from a C++ DLL

I've been tasked with writing a new interface to a legacy C++ DLL I don't have the source code for, which - for reasons beyond me - accesses a global class in the legacy application directly.
From the application, it's something like:
extern Interface *App;
...
Interface App*; // A pointer to our interface class.
Then, from the legacy DLL:
if( App->GetStatus() ) return false;
The Interface class that App refers to is quite trivial to rewrite in C#, but how can I make it the equivalent of extern so that the legacy C++ DLL can access it?
Thanks!
You could try using Robert Giesecke's "UnmanagedExports" nuget package to achieve this functionality like so:
class Test
{
[DllExport("add", CallingConvention = CallingConvention.Cdecl)]
public static int TestExport(int left, int right)
{
return left + right;
}
}
However:
a) I believe this only works for methods, not classes and
b) the reason there isn't a native way to export a DLL in C# is because that the calling application must have the .NET framework loaded in order to access that entry point. This also applies to the UnmanagedExports nuget package that I linked to above.
You can hack your way around this by getting your C++ app to load mono before calling the C# app, but it doesn't sound like this is possible in your case.
(Also, UnmanagedExports will only work if you explicitly set a build target in your project's properties - eg. x86)

How to call methods from a C++ library in C#

I have a vendor's DLL that is meant to be called from C++, but I need to call it from C#.
Using an app called PE Explorer I can see the list of exported methods in the DLL (call it Protocol.dll for now) and even get an 'Undecorated C++ Function' signature like this:
public: unsigned int __thiscall Myco::Protocol::tMultiThingClient::GetThings(char (* const)[16],unsigned int)
How do I use something like that in C#? I know I use DllImport, I just don't know how to go from the signature above to a proper DllImport signature.
Total WAG:
[DllImport("Protocol.dll", EntryPoint="GetThings")]
public static extern void GetThings(ref string[], uint);
Is that even close? Is there a reference somewhere that translates between C++ declarations like char (* const)[16] and their C# equivalents?
You need to create a seperate project containing mixed assembly using C++ CLI. For this, you need to enable the CLR compiler switch in your project properties. Since, the project allows mixed assembly, you can call the C++ function, and also create a C# interface for your main program to call.
So, your main program will call the interface you implement inside your C++ CLI project, which will in turn call the C++ funtion inside the DLL.
Please beware of Marshalling and Thunking while you do this, if it applies to your system considerations.

Calling unmanaged methods from managed code

Let's assume I have an unmanaged class Test:
class Test
{
public:
int SomeMethod(int a, bool b);
};
To create a new instance of Test, I'd:
Test *test = new Test();
My goal is to embed Mono so that managed code could call unmanaged methods (like Test::SomeMethod) in a specific object. I represent that object by passing a pointer of that object to the managed method, like that:
void *args[1];
args[0] = &test;
mono_runtime_invoke(init, NULL, args, NULL);
Here is how the managed method that is being invoked looks like:
public static void Init(IntPtr test)
{
}
From here, how can I call Test.SomeMethod?
I thought about using emitting the CALLI instruction, using System.Reflection.Emit, but how can I refer to the object that the pointer test (the first parameter of Init) is referring to?
I do not want to use DllImport.
You might be interested in CXXI. It creates a managed assembly based on your C++ headers and allows you to work with C++ objects as if they were normal managed objects.
As far as I understand it, it's not finished yet and works only with C++ code compiled by GCC.
Can't be done (Or at least shouldn't be done).
You're trying to directly mix two completely different execution environments - the reason why DLLImport exists is to allow the compiler to solve this problem.
In .NET, you can create mixed-mode applications (C++/CLI) which allow managed code and unmanaged code to co-exist in the same binary (and call each other), but since you're talking about mono, I'm assuming that option is out.
Managed environments like .NET have strict type rules, garbage collection and other features that simply don't work with unmanaged code and data.
You can use an internal call, if you don't want to use DllImport.
See https://github.com/mono/mono/blob/master/samples/embed/teste.c the mono_add_internal_call() invocation and the C# code in the test.cs file.
This works mostly like DllImport, except there is no marshalling done for you (a string object in C# code will appear as a MonoString* in the C code, not as a char*, for example).
In any case, note that both the function you could access with DllImport and the function pointer registered with mono_add_internal_call() must be C functions, not C++ member methods.

C# DLL Missing Public Functions

I am attempting to write a DLL using the C# .NET Framework 2.0. Everything compiles okay, but when I try to access the DLL from my application, it fails when attempting to get the procedure address. So, I oped the DLL in Dependency Walker, and all of my public functions are missing!
My DLL, so far, is fairly straightforward:
namespace MyDll_Namespace
{
public class MyDllClass
{
public static int Func1( /* params */ ) { /* ... */ }
public static int Func2( /* params */ ) { /* ... */ }
public static int Func3( /* params */ ) { /* ... */ }
public static int Func4( /* params */ ) { /* ... */ }
}
}
There's not much else, just a few constants and delegates defined inside the class, as well as outside the class in the namespace. Any thoughts or suggestions would be much appreciated. Thanks.
Dependency walker is for win32 DLLs (which is native code), not .NET assemblies (which is managed code). It won't find methods in an arbitrary class (even if they are static). If you need to call managed code from native code, there are ways of doing that, but it's not pretty.
If you want to use your dll from managed code, it's a lot easier. Check out System.Assembly and Activator.
An example of this:
var assembly = Assembly.LoadFile(#"\path\to\your.dll");
var mydllclass_type = assembly.GetType("MyDllClass");
var instance = Activator.CreateInstance(mydllclass_type);
The instance will be an object. To call the methods, you need to use reflection, because the interface is not known at compile-time.
If you are creating a plugin system, the best way is to have a common interface or abstract base for all plugins, and have that referenced by your program. Those third parties who implement a plugin, will also reference this contract. In this case, the last line changes a bit:
var instance = (IMyDllClass)Activator.CreateInstance(mydllclass_type);
Now you can use the methods like in a regularly constructed object.
Part of the problem here is that dependency walker is a tool for native applications. It doesn't understand managed code and hence won't display any of the managed types + methods that you've defined.
I'm confused by this line in your question
when I try to access the DLL from my application, it fails when attempting to get the procedure address
This sounds a bit like an error I would see in a native application, not a managed one. Are you trying to access the C# code from a native application? If so this can only be done via COM magic and not via direct calling. Can you explain in more detail what is going on here?
Try .net Reflector to see exactly what's inside your built DLL (in order to make sure everything is the way it is supposed to).
Also make sure you're in release mode while building your DLL before referencing it... I don't know if it's going to change anything, but it worths the try =)
You need to add a reference to your dll and the runtime will automatically allow you to call your function. Here is a little tutorial on writing a .net class library.
I decided to write my DLLs in C++. However, here is a bunch of useful information I found for using managed code from unmanaged code:
Is it possible to use a DLL created using C# in an unmanaged VC++ application?
How do I call C++/CLI (.NET) DLLs from standard, unmanaged non-.NET applications?
Using managed code in an unmanaged application
Using Managed Components from Unmanaged Code
An Overview of Managed/Unmanaged Code Interoperability
Unmanaged Exports
Calling Managed .NET C# COM Objects from Unmanaged C++ Code
All-In-One Code Framework
CLR Hosting APIs
How To: Migrate to /clr
How to call a managed DLL from native Visual C++ code in Visual Studio.NET or in Visual Studio 2005

How to bind c++ dll to my C# program - winCE

i need to bind C++ dll to my C# WinCE program. (scanner dll)
how i can do it ?
thank's in advance
You need to use Interop to call into unmanaged code.
using System.Runtime.InteropServices; // DllImport
public class Win32 {
[DllImport("User32.Dll")]
public static extern void SetWindowText(int h, String s);
}
Here is an article that discusses the topic in detail (also where the code is sourced from).
http://msdn.microsoft.com/en-us/magazine/cc301501.aspx
An alternative to InterOp is to write a C++ DLL using CLR extensions which acts as a wrapper to the traditional C++ DLL. This gives you a chance to handle unusual types, e.g. custom structures or classes, if Marshaling isn't going to work. (According to MSDN you can extend the Marshaling support (http://msdn.microsoft.com/en-us/library/bb531313.aspx) but I haven't tried this personally, and depending on what you're doing it might be a lot of work).
For example if you want to access a DLL which exports a class, you can have a wrapper DLL which owns an instance of the C++ class and defines a .NET class which maps onto the C++ class. For example, here's a snippet from a C++/CLR DLL which we use to make one of our old C++ DLLs available in .NET:
// This is the constructor for the CLR (managed) object
FileInf::FileInf()
{
// Create the C++ (unmanaged) object
m_pFileInf = gcnew DILib::FileInf();
}
// This is a managed interface which replicates the old
// unmanaged functionality
bool FileInf::IsDirectory()
{
return m_pFileInf->IsDirectory();
}
I'd say if InterOp works then stick with it, but I'm not sure if it's the best way to solve every C++ / .NET interfacing problem, and this is an alternative.

Categories