More Group Sites
Education Books
School Rankings
Jobless Net
Better Home
Enviro++
更好教育论坛
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Share
Options
View
Go to last post Go to first unread
hong  
#1 Posted : Friday, 23 October 2009 2:14:09 PM(UTC)
hong

Rank: Administration

Reputation:

Groups: AcademicCoachingSchool, admin, Administration, BookSeller, CatholicSchool, CoachingAdult, CoachingProfessional, CoachingSports, ExtraCurriculumCoaching, IndependentSchool, Moderator, MusicTeacher, PrivateSchool, PublicSchool, SelectiveSchool, tutor
Joined: 23/11/2008(UTC)
Posts: 523

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?

Edited by user Monday, 2 November 2009 3:14:49 AM(UTC)  | Reason: Not specified

Sponsor
wcollin  
#2 Posted : Monday, 2 November 2009 1:38:34 AM(UTC)
wcollin

Rank: Newbie

Reputation:

Groups: Member
Joined: 1/11/2009(UTC)
Posts: 1

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.


hong  
#3 Posted : Monday, 2 November 2009 2:44:43 AM(UTC)
hong

Rank: Administration

Reputation:

Groups: AcademicCoachingSchool, admin, Administration, BookSeller, CatholicSchool, CoachingAdult, CoachingProfessional, CoachingSports, ExtraCurriculumCoaching, IndependentSchool, Moderator, MusicTeacher, PrivateSchool, PublicSchool, SelectiveSchool, tutor
Joined: 23/11/2008(UTC)
Posts: 523

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.
hong  
#4 Posted : Monday, 2 November 2009 3:32:57 AM(UTC)
hong

Rank: Administration

Reputation:

Groups: AcademicCoachingSchool, admin, Administration, BookSeller, CatholicSchool, CoachingAdult, CoachingProfessional, CoachingSports, ExtraCurriculumCoaching, IndependentSchool, Moderator, MusicTeacher, PrivateSchool, PublicSchool, SelectiveSchool, tutor
Joined: 23/11/2008(UTC)
Posts: 523

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.

Edited by user Monday, 2 November 2009 7:45:23 AM(UTC)  | Reason: Not specified

hong  
#5 Posted : Monday, 2 November 2009 5:59:04 AM(UTC)
hong

Rank: Administration

Reputation:

Groups: AcademicCoachingSchool, admin, Administration, BookSeller, CatholicSchool, CoachingAdult, CoachingProfessional, CoachingSports, ExtraCurriculumCoaching, IndependentSchool, Moderator, MusicTeacher, PrivateSchool, PublicSchool, SelectiveSchool, tutor
Joined: 23/11/2008(UTC)
Posts: 523

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.

Edited by user Tuesday, 1 September 2015 9:04:55 PM(UTC)  | Reason: Not specified

hong  
#6 Posted : Monday, 2 November 2009 7:53:25 AM(UTC)
hong

Rank: Administration

Reputation:

Groups: AcademicCoachingSchool, admin, Administration, BookSeller, CatholicSchool, CoachingAdult, CoachingProfessional, CoachingSports, ExtraCurriculumCoaching, IndependentSchool, Moderator, MusicTeacher, PrivateSchool, PublicSchool, SelectiveSchool, tutor
Joined: 23/11/2008(UTC)
Posts: 523

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 Name
int - 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.

Edited by user Saturday, 14 November 2009 3:42:01 AM(UTC)  | Reason: Not specified

Rss Feed  Atom Feed
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.