|
|
 Rank: Administration Groups: Administration
Joined: 11/23/2008 Posts: 329 Points: 693 Location: Australia
|
How to call native C/C++ functions with pointers' parameters from C#? C# is one of the primary languages of the .NET platform, thus, runs in a managed environment and cannot call unmanaged code without marshaling between the managed and unmanaged code or other intermediate mechanisms. I have a C++ dll that need to expose static functions (via a class) with pointers and char* as parameters. What's the easiest way for a C# application (web application that cannot be in the same solution) to be able to call the functions?
|
|
|
|
|
|
Rank: Newbie Groups: Member
Joined: 11/1/2009 Posts: 1 Points: 3 Location: China
|
Are your global functions in C or C++? I have a similar issue - I want to call C API from a .net language. If you found the solution, please let me know.
|
|
 Rank: Administration Groups: Administration
Joined: 11/23/2008 Posts: 329 Points: 693 Location: Australia
|
I was useing C++ classes. I looked at the .net assesmbly using ILDASM and found they are all global functions. There is no current tool (including ILASM) can call global functions exported from an assembly in .net. First I added a namespace to the global functions. They were still global in spite of the existence of namespace prefix of the functions. Then I realise the problem - I didn't add ref to make the class as a reference. So the class declaration should like "public ref class MyClass". Here is the example: Code:#pragma once namespace MyNameSpace { public ref class MyClass { public: MyClass(void); static void DoSomething();
public: ~MyClass(void); }; } In your situation, you can wrap your C functions into classes. In order to use it as a reference in .net, they must be in a class. Now we can see the functions under the namespace in the assembly and the functions can be referenced in a .net language. However, the old issue remains - C# cannot call the unmanaged C++ functions with pointers as parameters. It seems we cannot avoid the marshaling between the managed and unmanaged code.
|
|
 Rank: Administration Groups: Administration
Joined: 11/23/2008 Posts: 329 Points: 693 Location: Australia
|
Hey, I found an easier way to call flat C API. The mechanism is PInvoke or P/Invoke. It stands for Platform Invoke. With P/Invoke, you don't need to dynamically load the dll and use GetProcAddress() as these are bulit in P/Invoke. See the following example: Code:using System; using System.Runtime.InteropServices;
public class MyClass { [DllImport("myDll.dll", EntryPoint="myFunction")] static extern void myFunction(string myString);
} We declare myFunctio() static extern because we do not write the body of the function and it will not depend on the class instance data. Using C# attribute DllImport we specify the DLL "myDll.dll" where the function will be defined and the entry point. We can find the entry point via Dependency Walker. If you run your code and see a System.DllNotFoundException, you can copy the dll to the binary path or specify the dll path. Of course, this is a extremely simple example, when more complex data types are involved we still need to do marshaling. BTW, the DllImport attribute supports other arguments to tweak its behavior, refer to MSDN for DllImport documentation.
|
|
 Rank: Administration Groups: Administration
Joined: 11/23/2008 Posts: 329 Points: 693 Location: Australia
|
I googled the internet and found more ways that native code and managed code can interact and call each other depending on the nature of API of your native code. 1. If your native code is just C functions in a native dll, i.e. global functions or static methods, call the static dll methods directly via P/Invoke. 2. If your native code is exposed using COM, the CLR’s COM Interop can provide access. 3. If you have a C++ class, you could add COM support. 4. If you have a C++ class, you can write a custom wrapper using C++/CLI and expose a new managed class. In other words, write a C++.NET class which is accessible from C# in a managed assembly.
We have discussed choice 1 in the previous topic. Unfortunately, choice 2 doesn't apply to my situation. Choice 3 requires the knowledge of COM.
C++ is the only managed language which allows you to mix both managed and native code. You can create your wrappers in managed C++ by creating "Visual C++ CLR Class Library". CLR means Common Language Runtime of .net framework which makes C# and C++ managed. Then you can add a reference to your mangaged C++ dll and you will completely avoid having to do "DLLImport" as in choice 1. However, with the wrapper in choice 4, we still cannot avoid the marshaling between the managed code and native code.
|
|
 Rank: Administration Groups: Administration
Joined: 11/23/2008 Posts: 329 Points: 693 Location: Australia
|
Unmanaged Data Types and the Equivalent Managed Types for marshaling Here are some common native data types and their equivalent managed types for marshaling: Unmanaged C Type - Managed Class Nameint - System.Int32 int* - IntPtr char* - System.String or System.StringBuilder const char* - System.String or System.StringBuilder char - System.Char For using P/Invoke with custom data types, you can use "MarshalAs" for marshaling instructions. See examples at Call unmanaged code with int* or char* using simple DllImport.
|
|
|
Guest |