前言:为了介绍C#写界面,C++写算法的快捷开发方式,C#与C++的交互,首先介绍c++,C#内部的DLL,COM调用。
一, 静态的Lib:静态的lib经过编译后只有.h和.lib文件,没有dll,因为实现部分也包含在lib中,这就是与动态dll的区别。还有在写静态lib的时候不需要在使用导出关键字_declspec(dllexport)。一般有2中方法调用静态lib,如下实例:
静态lib:CPPLib->test.h
 #pragma once
#pragma once

 class CTest
class CTest
 {
{
 public:
public:
 CTest(void);
    CTest(void);
 public:
public:
 ~CTest(void);
    ~CTest(void);
 public:
public:
 int Add(int x, int y);
    int Add(int x, int y);
 int Square(int x);
    int Square(int x);
 };
};

 //函数的实现必须写在.cpp文件中,否则编译有错,说重复定义
//函数的实现必须写在.cpp文件中,否则编译有错,说重复定义
 int Max(int x, int y);
int Max(int x, int y);静态lib的实现文件: CPPLib->test.cpp
 #include "StdAfx.h"
#include "StdAfx.h"
 #include "Test.h"
#include "Test.h"

 CTest::CTest(void)
CTest::CTest(void)
 {
{
 }
}

 CTest::~CTest(void)
CTest::~CTest(void)
 {
{
 }
}

 int CTest::Add(int x, int y)
int CTest::Add(int x, int y)
 {
{
 return x+y;
 return x+y;
 }
}
 int CTest::Square(int x)
int CTest::Square(int x)
 {
{
 return x*x;
    return x*x;
 }
}

 int Max(int x, int y)
int Max(int x, int y)
 {
{
 return x;
    return x;
 }
}
client调用CPPLibClient->CPPibClient.cpp
 #include "stdafx.h"
#include "stdafx.h"
 //#include "test.h"
//#include "test.h"
 //#include <windows.h>
//#include <windows.h>
 //#include <string>
//#include <string>
 //#include <assert.h>
//#include <assert.h>


 //#include "../CppLib/test.h"
//#include "../CppLib/test.h" 
 //#pragma comment(lib,"../debug/CppLib.lib")
//#pragma comment(lib,"../debug/CppLib.lib")
 //#pragma 使用法
//#pragma 使用法


 //#include "test.h"
//#include "test.h"
 //修改编译选项调用静态库
//修改编译选项调用静态库
 //需要修改:include的path,lib的path,和加入lib的名字,如下:
//需要修改:include的path,lib的path,和加入lib的名字,如下:
 //C++->General->additional include directories
//C++->General->additional include directories
 //Linker->General->additional library directories
//Linker->General->additional library directories
 //linker->input->additional dependencies
//linker->input->additional dependencies

 //不能动态加载静态的lib库
//不能动态加载静态的lib库
 //HMODULE m_handle = LoadLibrary(L"../debug/CppLib.Lib");
//HMODULE m_handle = LoadLibrary(L"../debug/CppLib.Lib");
 //GetProcAddress(m_handle, "Max");
//GetProcAddress(m_handle, "Max");
 //FreeLibrary(m_handle);
//FreeLibrary(m_handle);

 int _tmain(int argc, _TCHAR* argv[])
int _tmain(int argc, _TCHAR* argv[])
 {
{
 CTest test;
    CTest test;
 int a = test.Add(10,20);
    int a = test.Add(10,20);
 printf("the result is :%d\n",a);
    printf("the result is :%d\n",a);
 a = Max(10,20);
    a = Max(10,20);
 printf("the result is :%d\n",a);
    printf("the result is :%d\n",a);
 return 0;
    return 0;
 
    
 }
}

调用方法:可以看出对于静态的只可以使用修改编译选项和pragma comment()来调用,不能使用loadlibrary()来调用。
二 ,动态DLL:在动态dll中,可以导出变量,函数和整个类。编译后有.h,.lib和dll文件,真正的实现包含在dll中,所以在client调用动态dll的时候,必须要使用dll,最后和client的放在同意目录下。要导出必须使用导出关键字_declspec(dllexport)。有时还使用extern “C”,为了使导出能够与C兼容,一般我们都加extern “c”。
一般调用有3中方法,实例如下:
实例1:演示了导出变量和函数,和前2中调用方法,修改编译选项和pragma comment().
动态dll:CPPdll->test.h
 #pragma once
#pragma once


 extern "C" _declspec(dllexport) int nCppDll;
extern "C" _declspec(dllexport) int nCppDll;
 extern "C" _declspec(dllexport) int fnCppDll(void);
extern "C" _declspec(dllexport) int fnCppDll(void);

 extern "C" _declspec(dllexport) int Max(int a, int b);
extern "C" _declspec(dllexport) int Max(int a, int b);
 extern "C" _declspec(dllexport) int Min(int a, int b);
extern "C" _declspec(dllexport) int Min(int a, int b);
动态dll的实现:CPPDLL->test.cpp
 #include "StdAfx.h"
#include "StdAfx.h"
 #include "Test.h"
#include "Test.h"


 // This is an example of an exported variable
// This is an example of an exported variable
 int nCppDll=100;
 int nCppDll=100;

 // This is an example of an exported function.
// This is an example of an exported function.
 int fnCppDll(void)
int fnCppDll(void)
 {
{
 return 42;
    return 42;
 }
}

 int Max(int a, int b)
int Max(int a, int b)
 {
{
 if(a>=b)return a;
if(a>=b)return a;
 else
else
 return b;
return b;
 }
}
 int Min(int a, int b)
int Min(int a, int b)
 {
{
 if(a>=b)return b;
if(a>=b)return b;
 else
else
 return a;
return a;
 }
} 
client的调用:cppclient->cppclient.cpp
 #include "stdafx.h"
#include "stdafx.h"

 #pragma comment(lib, "../debug/CppDll.lib")
#pragma comment(lib, "../debug/CppDll.lib")
 extern "C"  int Max(int a,int b);//_declspec(dllimport)
extern "C"  int Max(int a,int b);//_declspec(dllimport)
 extern "C" int Min(int a,int b); //_declspec(dllimport)
extern "C" int Min(int a,int b); //_declspec(dllimport)
 extern "C" _declspec(dllimport) int nCppDll;
extern "C" _declspec(dllimport) int nCppDll;
 extern "C" int fnCppDll(void);
extern "C" int fnCppDll(void);

 //#include "test.h"
//#include "test.h"
 //修改编译选项调用静态库
//修改编译选项调用静态库
 //需要修改:include的path,lib的path,和加入lib的名字,如下:
//需要修改:include的path,lib的path,和加入lib的名字,如下:
 //C++->General->additional include directories
//C++->General->additional include directories
 //Linker->General->additional library directories
//Linker->General->additional library directories
 //linker->input->additional dependencies
//linker->input->additional dependencies

 int _tmain(int argc, _TCHAR* argv[])
int _tmain(int argc, _TCHAR* argv[])
 {
{
 int a;
    int a;
 a  =Min(8,10);
    a  =Min(8,10);
 printf("比较的结果为 %d\n",a);
    printf("比较的结果为 %d\n",a);
 a= Max(8,10);
    a= Max(8,10);
 printf("比较的结果为%d\n",a);
    printf("比较的结果为%d\n",a);
 
    
 printf("导出的变量:%d\n",nCppDll);
    printf("导出的变量:%d\n",nCppDll);

 a = fnCppDll();
    a = fnCppDll();
 printf("fnCppDll的结果:%d\n",a);
    printf("fnCppDll的结果:%d\n",a);    

 return 0;
    return 0;
 }
}上面演示了对一般变量和函数的导出的调用方法中的其中的2中,修改编译选项和pragma comment(),当使用pragma comment()的使用,应当注意:
使用#pragma隐式加载动态库
对于变量,必须申明且不能include头文件。extern "C" _declspec(dllimport) int nCppDll;
对于函数,或include头文件,或是申明。extern "C" int fnCppDll(void);
对于类,最好使用函数封装导出指针供使用。
参考:http://www.cppblog.com/mzty/archive/2006/07/24/10419.html
实例2:演示类的导出和使用动态加载来调用。
动态dll的类导出:CPPDll2->test.h
 #pragma  once
#pragma  once
 //#include "boost/shared_ptr.hpp"
//#include "boost/shared_ptr.hpp"

 class Test
class Test 
 {
{
 public:
public:
 virtual ~Test() {}
 virtual ~Test() {}
 virtual void DoIt() =0;
 virtual void DoIt() =0;
 };
};

 //extern "C" _declspec(dllexport)  std::auto_ptr<Test> CreateTest();
//extern "C" _declspec(dllexport)  std::auto_ptr<Test> CreateTest();
 //extern "C" _declspec(dllexport) boost::shared_ptr<Test> CreateTest();
//extern "C" _declspec(dllexport) boost::shared_ptr<Test> CreateTest();
 extern "C" _declspec(dllexport) Test* CreateTestPtr();
extern "C" _declspec(dllexport) Test* CreateTestPtr();

 extern "C" _declspec(dllexport) void DeleteTestPtr(Test*);
extern "C" _declspec(dllexport) void DeleteTestPtr(Test*);
动态dll的类导出的实现:CPPDll2->test.cpp
 //test.cpp
//test.cpp
 #include "stdafx.h"
#include "stdafx.h"
 #include "Test.h"
#include "Test.h"
 #include <stdio.h>
#include <stdio.h>
 //#include <memory>
//#include <memory>
 //#include "boost/shared_ptr.hpp"
//#include "boost/shared_ptr.hpp"


 class CTest : public Test
class CTest : public Test
 {
{
 public:
public:
 virtual void DoIt()
    virtual void DoIt()
 { printf("Should do something\n"); }
   { printf("Should do something\n"); }
 };
};

 //std::auto_ptr<Test> CreateTest()
//std::auto_ptr<Test> CreateTest()
 //{
//{
 //    return std::auto_ptr<Test>(new CTest);
//    return std::auto_ptr<Test>(new CTest);
 //}
//}


 //boost::shared_ptr<Test> CreateTest()
//boost::shared_ptr<Test> CreateTest() 
 //{
//{ 
 //    return boost::shared_ptr<Test>(new CTest);
//    return boost::shared_ptr<Test>(new CTest);  
 //}
//}

 Test* CreateTestPtr()
Test* CreateTestPtr()
 {
{
 return new CTest();
    return new CTest();
 }
}

 void DeleteTestPtr(Test* t)
void DeleteTestPtr(Test* t)
 {
{
 if(t != NULL)
    if(t != NULL)
 {
    {
 delete t;
        delete t;
 t = NULL;
        t = NULL;
 }
    }

 }
}对loadlibrary的分装,可以作为tools:
 //library.h
//library.h
 #pragma once
#pragma once
 #include <windows.h>
#include <windows.h>
 #include <string>
#include <string>
 #include <assert.h>
#include <assert.h>

 class Library
class Library
 {
{
 public:
public:

 explicit Library(const wchar_t* name)
 explicit Library(const wchar_t* name)
 {
 {
 m_handle = LoadLibrary(name);
  m_handle = LoadLibrary(name);
 assert(m_handle);
  assert(m_handle);
 if (!m_handle)
  if (!m_handle)
 throw std::runtime_error(std::string("Could not find library file:"));
   throw std::runtime_error(std::string("Could not find library file:"));  
 }
 }

 ~Library()
 ~Library()
 {
 {
 FreeLibrary(m_handle);
  FreeLibrary(m_handle);
 }
 }

 void* GetProc(const char* name)
 void* GetProc(const char* name)
 {
 {
 void* proc = ::GetProcAddress(m_handle, name);
  void* proc = ::GetProcAddress(m_handle, name);
 assert(proc);
  assert(proc);
 return proc;
  return proc;
 }
 }

 private:
private:
 HMODULE m_handle;
 HMODULE m_handle;
 };
};
client的调用:

 #include "stdafx.h"
#include "stdafx.h"
 #include "library.h"
#include "library.h"
 #include "../CppDll2/test.h"
#include "../CppDll2/test.h"

 int _tmain(int argc, _TCHAR* argv[])
int _tmain(int argc, _TCHAR* argv[])
 {
{
 
    
 typedef Test* (*CREATE)();
    typedef Test* (*CREATE)();
 typedef void (*DEL)(Test*);
    typedef void (*DEL)(Test*);    

 Library lib(L"CppDll2.dll");
    Library lib(L"CppDll2.dll");
 //std::auto_ptr<Test> test = ((std::auto_ptr<Test> ) lib.GetProc("CreateTest"));
    //std::auto_ptr<Test> test = ((std::auto_ptr<Test> ) lib.GetProc("CreateTest"));
 Test* test = (((CREATE)(lib.GetProc("CreateTestPtr")))());
    Test* test = (((CREATE)(lib.GetProc("CreateTestPtr")))());
 test->DoIt();
    test->DoIt();
 ((DEL)(lib.GetProc("DeleteTestPtr")))(test);
    ((DEL)(lib.GetProc("DeleteTestPtr")))(test);
 return 0;
    return 0;
 }
}
上面的是对类的动态调用,注意需要include头文件哦!
//通过API动态加载动态库
//对于类的导出,最好使用函数封装,导出类的指针。
//动态加载dll, 如果导出的函数只使用 extern,而没有使用extern "C" 则GetProcAdress会找不到函数的指针,要想找到可以使用真正要找的函数原型哦,可能是函数名后加@@。。。,也可以使用编号来找到需要的函数地址。
//但是如果导出函数使用extern "C"的话,导出函数的返回值不能是auto_ptr<>或shared_ptr<>哦,但是我们仍然可以使用智能指针哦,采用的方法是不使用return返回,使用函数的参数返回哦。//使用智能指针导出的更好的实现,请参考 http://www.cppblog.com/eXile 
//参考: http://www.cppblog.com/eXile/archive/2007/04/19/22262.html
//更多dll类型:http://www.vckbase.com/document/viewdoc/?id=1116
//调用约定:http://blog.chinaunix.net/u/21790/showart_265932.html
三 资源DLL
在C++中,我们可以建立纯资源的动态dll,比如说我们建立了一个动态的资源dll,里面增加一个string: id为IDS_APPLICATION,值为:aaa,
则我们可以在client动态调用如下:
 #include "stdafx.h"
#include "stdafx.h"
 #include <windows.h>
#include <windows.h>
 #include "../ResDll/resource.h"
#include "../ResDll/resource.h"

 int _tmain(int argc, _TCHAR* argv[])
int _tmain(int argc, _TCHAR* argv[])
 {
{
 HMODULE hModule=LoadLibrary(L"../debug/ResDll.dll");
    HMODULE hModule=LoadLibrary(L"../debug/ResDll.dll");
 if( NULL != hModule)
    if( NULL != hModule)
 {
    {
 TCHAR szName[200];
        TCHAR szName[200];
 ::LoadString(hModule,IDS_APPLICATION,szName,200);
        ::LoadString(hModule,IDS_APPLICATION,szName,200);
 FreeLibrary(hModule);
        FreeLibrary(hModule);
 }
    }
 return 0;
    return 0;
 }
}
资源还可以是其他的比如是icon,bitmap。。。。等,有对应的load。()函数去调用。
四,总结
熟悉dll调用的3中方法,其中对静态的调用只有2中方法,一般对类的导出调用要使用函数封装哦!:~
代码下载:http://www.cppblog.com/Files/mzty/DLLTest.rar