一 引子
1)使用VS2005,Native C++,C#,CLI/C++。
2)主要介绍CLI/C++和Native C++, C#的交互,最总能够实现以CLI/C++为中介的Native C++与C#的互调。
二 实例
1)实现一个CLI/C++的Dll,在此Dll中包含一个RefClass能够被C#的exe调用。(实现过程:在VS中建立C++ CLR Class library 的一个Project,然后增加一个类RefClass)代码如下:
refclass.h文件:
#pragma once
namespace ClrCppDll
{
public ref class RefClass
{
public:
RefClass(){}
RefClass(int _x, int _y) : x(_x), y(_y)
{
}
void PrintSelf();
private:
int x;
int y;
};
}
refclass.cpp文件:
#include "stdafx.h"
#include "refclass.h"
using namespace System;
using namespace ClrCppDll;
void RefClass::PrintSelf()
{
System::Console::WriteLine("hello, i am a ref cpp class");
System::Console::WriteLine("x is {0}",x);
System::Console::WriteLine("y is {0}",y);
}
2)能够调用上面第1)步中的CLI/C++的Dll中class的C#的exe。(实现过程:在VS建立C#的console Application,然后reference 前面的1)生成的Dll)代码如下:
Program.cs文件:
using System;
using System.Collections.Generic;
using System.Text;
namespace CsharpTest
{
class Program
{
static void Main(string[] args)
{
ClrCppDll.RefClass refClass = new ClrCppDll.RefClass(2,4);
refClass.PrintSelf();
}
}
}
上面2步的代码下载:
http://www.cppblog.com/Files/mzty/CSharpCPPCLI1.rar (实现CLI/C++的dll能够被C#调用)
3)对1)实现的CLI/C++的Dll中增加能够被Native C++调用的NativeClass。代码如下:
NativeClass.h文件:
#pragma once
namespace ClrCppDll
{
public class NativeClass
{
public:
NativeClass(){}
NativeClass(int _x, int _y) : x(_x), y(_y)
{}
void printSelf();
private:
int x;
int y;
};
}
NativeClass.cpp文件:
#include "stdafx.h"
#include <iostream>
#include "nativeclass.h"
using namespace ClrCppDll;
void NativeClass::printSelf()
{
std::cout<<"hello,i am a native cpp class!"<<std::endl;
std::cout<<"x is "<<x<<std::endl;
std::cout<<"y is "<<y<<std::endl;
}
问题: 如果我们直接在NativeC++的exe调用上面CLI/C++中的NativeClass,会有问题,Error 1 error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h 8,这是为什么那,我们想想我们一般的Native C++的DLL的调用,都要将要被调用的Class或funtion导出才可以调用,想到这里我们也对我们的NativeClass进行导出。(怎么导出可以看下面的代码)但是当增加了对NativeClass的导出,调用的时候仍然有上面的error,Error 1 error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h 9,最后只有查找资料(没有找到)问别人(没有问到),最后想到使用导出函数试试,一试果然可行啊,哈哈哈,so Happy!
其实后来发现是我加的导出__declspec(dllexport)的位置不对,应该是在class关键字后面,总之导出类也是可以的。导出类的代码可以下载新的sample,增加导出和导出的函数代码如下:
(导出不久需要下面的2文件,还的定义宏 CLR_CPP_DLL在编译选项中,或直接写在文件中)
clrcppdll.h
// ClrCppDll.h
#pragma once
#ifdef CLR_CPP_DLL
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP
#endif
namespace ClrCppDll
{
DLLIMPEXP void CallNativeClassPrintSelf();
}
clrcppdll.cpp文件:
// This is the main DLL file.
#include "stdafx.h"
#include "NativeClass.h"
#include "ClrCppDll.h"
DLLIMPEXP void ClrCppDll::CallNativeClassPrintSelf()
{
ClrCppDll::NativeClass test(10,20);
test.printSelf();
}
4)建立一个NativeC++的exe来调用1)生成的CLI/C++的Dll中的3)增加的NativeClass(实现过程:建立一个Native C++的console application)代码如下:
cpptest.cpp文件:(经过上一步问题的反复折磨,终于搞定)(同时别忘了要在编译选项中指定lib和lib的路径)
// CppTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "../ClrCppDll/clrcppdll.h"
int _tmain(int argc, _TCHAR* argv[])
{
/**//*ClrCppDll::NativeClass test(5,6);
test.PrintSelf();*/
ClrCppDll::CallNativeClassPrintSelf();
return 0;
}
上面四步总代码下载:
http://www.cppblog.com/Files/mzty/CSharpCPPCLI2.rar (实现CLI/C++的dll同时被Native C++和C#的调用)
5)扩展,增加在NativeClass中调用RefClass的funtion, 和RefClass中调用NativeClass的function。
代码下载:
http://www.cppblog.com/Files/mzty/CSharpCPPCLI3.rar (最后代码下载,包含NativeClass与RefClass的互调)
http://www.cppblog.com/Files/mzty/CSharpCPPCLI32.zip (包含native class的导出也调用)
三 总结
1) CLI/C++中如果想导出让NativeC++使用,则最好导出函数,也可以导出类。
2) CLI/C++的DLL可以没有像一般的NativeC++的Dll中的DllMain()函数。
3) CLI/C++如果想导出让C#使用,则一般是ref class。