最近又摊上事了,这会轮到C#调用C++的库出问题了,你说一个小小的protection key,怎么问题总是不断呢,伤神啊,作一个TS容易吗!
闲话少叙,附上本次操作的记录,以为纪念:
1.建立Native DLL
这个很简单,在vs里面新建一个Win32 Console Application,选择DLL即可,然后选择empty工程,接着加入自己的DLL头文件和实现代码cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// NativeCppDll.h #pragma once #ifndef NATIVECPPDLL_CLSSS_EXPORTS #define NATIVECPPDLL_CLSSS_EXPORTS __declspec(dllexport) #else #define NATIVECPPDLL_CLSSS_EXPORTS __declspec(dllimport) #endif class NATIVECPPDLL_CLSSS_EXPORTS TestNative { public: TestNative(); int Check(int feature); private: long handle; int status; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// NativeCppDll.cpp #include "NativeCppDll.h" #include <iostream> using namespace std; TestNative::TestNative() { handle = 0; status = 0; } int TestNative::Check(int feature) { status = 1+1; //此处涉及到公司的东西,用1+1替换了 return status; } |
我们的Native库就算写好了,build后通过CFF查看export directory,会发现导出表中包含class名字和Check方法??
2.新建托管DLL
由于Native库中定义的是一个类,通过网上的一番搜罗,没看到有人直接通过DLLImport来使用类的,一般都是将此Dll封装为另一个托管的dll,然后供C#直接使用
这一步也很简单,唯一不同的,是新建工程时,要选择CLR- -Class Library。同样是建立一个新工程,注意在工程里链接NativeCppDll.lib,然后添加代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// ManageCppDll.h #pragma once //#define NATIVECPPDLL_CLSSS_EXPORTS #include "..\\NativeCPPDll\NativeCPPDll\NativeCppDll.h" //Native库的头文件 using namespace System; namespace ManageCppDll { public ref class TestManage { public: TestManage(); ~TestManage(); int TestManage::Check(int feature); private: // 类TestNative的指针,用来调用类TestNative的成员函数 TestNative *m_pImp; }; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// ManageCppDll.cpp #include "stdafx.h" #include "ManageCppDll.h" #include <vcclr.h> namespace ManageCppDll { // 在构造函数中创建类TestNative的对象并在析构函数中将该对象销毁 // 所有的成员函数实现都是通过指针m_pImp调用类TestNative的相应成员函数实现 TestManage::TestManage() { m_pImp = new TestNative(); } TestManage::~TestManage() { delete m_pImp; } int TestManage::Check(int feature) { return m_pImp->Check(feature); } }; |
(原文中强调所有public的方法都需要单独重新声明定义,private的则可以直接使用,我没有测试是否确实如此,暂且放置)
build之后,用CFF查看产生的ManageCppDll.dll,各种特征和c#编译出来的程序一模一样
3.使用C#程序调用
新建一个C#的winForm工程,添加一个textbox和button,然后引用ManageCppDll.dll,并在button_click()中添加如下代码:
1 2 3 4 5 6 7 8 9 10 |
using ManageCppDll; private void button1_Click(object sender, EventArgs e) { TestManage tm = new TestManage(); int status = tm.Check(0); textBox1.Text = "test:" + status; } |
本文的所有代码都参考了http://blog.csdn.net/starlee/article/details/2864588 上的内容然后改写而成,原文中有很详尽的说明和更多的代码示例,我只是为了测试公司接口参考了其中一部分,记录下来以作备忘,代码中涉及到公司环境的内容都删去了,可能在删除过程中会存在一些遗漏,但是大致步骤明了了,基本就不会有什么问题
补充:我是用VS2010 编译 Manage库的,但是在后续测试的时候,发现在2008系统上无法加载,查看import directory里面竟然 包含msvcr90.dll, 很奇怪,只好安装一个VC2008的redistribute,然后,然后就正常了