搜索
您的当前位置:首页正文

C#使用C++代码

来源:爱go旅游网
C# 中调用C++代码

首先必须要有一个声明,使用的是DllImport关键字: 包含DllImport所在的名字空间

using System.Runtime.InteropServices; public class XXXX{

[DllImport(“MyDLL.dll\")]

public static extern int mySum (int a,int b); }

[DllImport(“MyDLL.dll\")]

public static extern int mySum (int a,int b);

代码中DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在这个类中 在调用的时候

在类中的时候 直接 mySum(a,b);就可以了 在其他类中调用: XXXX. mySum(a,b);

[DllImport(“MyDLL.dll”)]在申明的时候还可以添加几个属性 [DllImport(“MyDLL.dll\

\

]

EntryPoint: 指定要调用的 DLL 入口点。默认入口点名称是托管方法的名称 。 CharSet: 控制名称重整和封送 String 参数的方式 (默认是UNICODE)

CallingConvention指示入口点的函数调用约定(默认WINAPI)(上次报告讲过的)

SetLastError 指示被调用方在从属性化方法返回之前是否调用 SetLastError Win32 API 函数 (C#中默认false )

int 类型

[DllImport(“MyDLL.dll\")] //返回个int 类型

public static extern int mySum (int a1,int b1); //DLL中申明

extern “C” __declspec(dllexport) int WINAPI mySum(int a2,int b2) {

//a2 b2不能改变a1 b1 //a2=.. //b2=... return a+b;

}

//参数传递int 类型

public static extern int mySum (ref int a1,ref int b1); //DLL中申明

extern “C” __declspec(dllexport) int WINAPI mySum(int *a2,int *b2) {

//可以改变 a1, b1 *a2=... *b2=... return a+b; }

DLL 需传入char *类型 [DllImport(“MyDLL.dll\")] //传入值

public static extern int mySum (string astr1,string bstr1); //DLL中申明

extern “C” __declspec(dllexport) int WINAPI mySum(char * astr2,char * bstr2) {

//改变astr2 bstr 2 ,astr1 bstr1不会被改变 return a+b; }

DLL 需传出char *类型 [DllImport(“MyDLL.dll\")] // 传出值

public static extern int mySum (StringBuilder abuf, StringBuilder bbuf ); //DLL中申明

extern “C” __declspec(dllexport) int WINAPI mySum(char * astr,char * bstr) {

//传出char * 改变astr bstr -->abuf, bbuf可以被改变 return a+b; }

DLL 回调函数

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

using System;

using System.Runtime.InteropServices;

public delegate bool CallBack(int hwnd, int lParam); //定义委托函数类型 public class EnumReportApp {

[DllImport(\"user32\")]

public static extern int EnumWindows(CallBack x, int y); public static void Main() {

CallBack myCallBack = new CallBack(EnumReportApp.Report); EnumWindows(myCallBack, 0);

}

public static bool Report(int hwnd, int lParam) {

Console.Write(\"Window handle is \"); Console.WriteLine(hwnd); return true; } }

DLL 传递结构 (见代码)

BOOL PtInRect(const RECT *lprc, POINT pt);

using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct Point { public int x; public int y; }

[StructLayout(LayoutKind.Explicit)] public struct Rect {

[FieldOffset(0)] public int left; [FieldOffset(4)] public int top; [FieldOffset(8)] public int right; [FieldOffset(12)] public int bottom; }

Class XXXX {

[DllImport(\"User32.dll\")]

public static extern bool PtInRect(ref Rect r, Point p); }

C#托管代码与C++非托管代码互相调用一(C#调用

C++代码&.net 代码安全)

在最近的项目中,牵涉到项目源代码保密问题,由于代码是C#写的,容易被反编译,因此决定抽取核心算法部分使用C++编写,C++到目前为止好像还不能被很好的反编译,当然如果你是反汇编高手的话,也许还是有可能反编译。这样一来,就涉及C#托管代码与C++非托管代码互相调用,于是调查了一些资料,顺便与大家分享一下

一. C# 中静态调用C++动态链接

1. 建立VC工程CppDemo,建立的时候选择Win32 Console(dll),选择Dll。 2. 在DllDemo.cpp文件中添加这些代码。

extern \"C\" __declspec(dllexport) int Add(int a,int b) {

return a+b; }

3. 编译工程。

4. 建立新的C#工程,选择Console应用程序,建立测试程序InteropDemo 5. 在Program.cs中添加引用:using System.Runtime.InteropServices; 6. 在pulic class Program添加如下代码: using System;

using System.Collections.Generic; using System.Text;

using System.Runtime.InteropServices;

namespace InteropDemo {

class Program {

[DllImport(\"CppDemo.dll\EntryPoint = \"Add\ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]

public static extern int Add(int a, int b); //DllImport请参照MSDN

static void Main(string[] args) {

Console.WriteLine(Add(1, 2)); Console.Read(); } } }

好了,现在您可以测试Add程序了,是不是可以在C# 中调用C++动态链接了,当然这是静态调用,需要将CppDemo编译生成的Dll放在DllDemo程序的Bin目录下

二. C# 中动态调用C++动态链接

在第一节中,讲了静态调用C++动态链接,由于Dll路径的限制,使用的不是很方便,C#中我们经常通过配置动态的调用托管Dll,例如常用的一些设计模式:Abstract Factory, Provider, Strategy模式等等,那么是不是也可以这样动态调用C++动态链接呢?只要您还记得在C++中,通过LoadLibrary, GetProcess, FreeLibrary这几个函数是可以动态调用动态链接的(它们包含在kernel32.dll中),那么问题迎刃而解了,下面我们一步一步实验

1. 将kernel32中的几个方法封装成本地调用类NativeMethod using System;

using System.Collections.Generic; using System.Text;

using System.Runtime.InteropServices;

namespace InteropDemo {

public static class NativeMethod {

[DllImport(\"kernel32.dll\EntryPoint = \"LoadLibrary\")]

public static extern int LoadLibrary( [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

[DllImport(\"kernel32.dll\EntryPoint = \"GetProcAddress\")]

public static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

[DllImport(\"kernel32.dll\EntryPoint = \"FreeLibrary\")] public static extern bool FreeLibrary(int hModule); } }

2. 使用NativeMethod类动态读取C++Dll,获得函数指针,并且将指针封装成C#中的委托。原因很简单,C#中已经不能使用指针了,如下

int hModule = NativeMethod.LoadLibrary(@\"c:\"CppDemo.dll\"); IntPtr intPtr = NativeMethod.GetProcAddress(hModule, \"Add\");

详细请参见代码 using System;

using System.Collections.Generic; using System.Text;

using System.Runtime.InteropServices;

namespace InteropDemo {

class Program {

//[DllImport(\"CppDemo.dll\EntryPoint = \"Add\ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]

//public static extern int Add(int a, int b); //DllImport请参照MSDN

static void Main(string[] args) {

//1. 动态加载C++ Dll

int hModule = NativeMethod.LoadLibrary(@\"c:CppDemo.dll\"); if (hModule == 0) return;

//2. 读取函数指针

IntPtr intPtr = NativeMethod.GetProcAddress(hModule, \"Add\");

//3. 将函数指针封装成委托

Add addFunction = (Add)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(Add));

//4. 测试

Console.WriteLine(addFunction(1, 2)); Console.Read(); }

///

/// 函数指针 ///

/// /// /// delegate int Add(int a, int b); } }

通过如上两个例子,我们可以在C#中动态或者静态的调用C++写的代码了

因篇幅问题不能全部显示,请点此查看更多更全内容

Top