一般的DLL导出类方法,一个简单的例子: dllExample.h:
#pragma once

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

class DLL_API ExportClass
{
pirvate:
int x;
public:
void foo();
};
dllExample.cpp:
#define DLL_EXPORTS
#include "dllExample.h"

void ExportClass::foo()
{
//do something...
return;
}
而外部代码只需要包含头文件,就会自动导入ExportClass的定义。 编译时连接该DLL对应的lib,运行时提供DLL文件,即可正常运行。 注意细节:#define DLL_EXPORTS在#include "dllExample.h"前面;
不过这种简单的DLL导出存在一个限制,如果我们导出的类中含有非C++基础类型: dllExample.h:
#pragma once

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

class DLL_API ExportClass
{
private:
std::string x; //此处的string类型导出是不安全的
public:
void foo();
};
我们知道, 对于STL,微软为每个版本的VS都有不同的实现,VS2008(VC90),VS2010(VC100),VS2013(VC120)。 由于不同的STL的实现,我们不能在不同的版本见直接传递std::string, 否则运行期可能出现不可预知的错误。 而事实上我们在ExportClass中的std::string x变量是不希望被外部直接使用的,也就是并没有export的必要,事实上,不建议让dll向外导出任何关于非C++基础类型的定义。 但是由于ExportClass需要向外导出(因为需要使用foo()函数),应该如何处理这样的矛盾呢? 对于这样的问题,我们需要使用C++的抽象类(其实就是java中的interface概念)来解决: 我们需要: 1. 申明一个只有纯虚函数和C++基础类型的基类,所有需要向外部导出的定义都包含在该类中。 2. 申明另一个类,继承该基类。 3. 实现一个返回基类函数指针的getInstance函数,即返回一个派生类实例的工厂方法。 4. 在外部代码中,通过多态机制访问该类。 dllExample.h:
#pragma once

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

class DLL_API ExportInterface
{
public:
virtual void foo() = 0;
};

extern "C" DLL_API ExportInterface*  getInstance();

#ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。
class ExportClass: public ExportInterface
{
pirvate:
std::string x; //由于外部代码对此不可见,此处的std::string是安全的。
public:
void foo(); //函数体在dllExample.cpp中实现
};
#endif
dllExample.cpp:
#define DLL_EXPORTS
#include "dllExample.h"

extern "C" DLL_API ExportInterface* getInstance()
{
ExportInterface* pInstance = new ExportClass();
return pInstance;
}

void ExportClass::foo()
{
//do something...
return;
}
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言语法进行编译,而不是C++的。

举例3:

之前的网络版本的例子存在问题,实际操作举例如下: dllExample.h文件
#pragma once


#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif


class DLL_API CExportInterface
{
public:
virtual long mutiply(int x, int y) = 0;
virtual long add(int x, int y) = 0;
}; 


extern "C" DLL_API CExportInterface*  getInstance();

#ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。
class CExportExample : public CExportInterface
{

public:
long mutiply(int x, int y); //函数体在dllExample.cpp中实现
long add(int x, int y);
};
#endif

dllExample.cpp文件
#define DLL_EXPORTS      //先定义DLL_EXPORTS,这样头文件才能被正确解析
#include "dllExample.h"



extern "C" DLL_API CExportInterface* getInstance()
{
CExportInterface* pInstance = new CExportExample();
return pInstance;
}


long CExportExample::mutiply(int x, int y)
{
long z = x * y;
return z;
}

long CExportExample::add(int x, int y)
{
long z = x + y;
return z;
}
为了防止new的对象没有删除,建议修改,待确认
extern "C" DLL_API CExportInterface* getInstance()
{
//CExportInterface* pInstance = new CExportExample();
//return pInstance;

static CExportExample pInstance;
return &pInstance;

}
DLLApplication.h文件
#pragma once

#include "dllExample.h"


DLL_API CExportInterface* getInstance();
DLLApplication.cpp文件
#include <iostream>
#include "DLLApplication.h"

int main()
{

CExportInterface* pInspectObj = getInstance();
long resultMutiply = pInspectObj->mutiply(2, 3);
long resultAdd = pInspectObj->add(2, 3);

std::cout << "Hello World!\n";

std::cout << "Hello World!\n";
}

举例4 考虑到大项目时

建立7个文件,配置application项目的属性 AVIInspectApplication.h
#pragma once
#include "DllAVIFunction.h"
DLL_AVI_API CAVIInterface* getInstance();
AVIInspectApplication.cpp
#include "AVIInspectApplication.h"

int main()
{


CAVIInterface *CAVIFunctionObj = getInstance();//创建一个类的对象,

long x = CAVIFunctionObj->mutiply(3, 4);

std::cout << "Hello World!\n";
}
DllAVIFunction.h
#pragma once

#include "DllAVIFunctionInterface.h"


extern "C" DLL_AVI_API CAVIInterface*  getInstance();

#ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。
class CAVIFunction : public CAVIInterface
{

public:
long mutiply(int x, int y); //函数体在dllExample.cpp中实现

};
#endif
DllAVIFunctionInterface.h
#pragma once

#include "DllAVIInclude.h"
#include "DllAVIParameterDefine.h"

#ifdef DLL_EXPORTS
#define DLL_AVI_API __declspec(dllexport)
#else
#define DLL_AVI_API __declspec(dllimport)
#endif


class DLL_AVI_API CAVIInterface
{
public:
virtual long mutiply(int x, int y) = 0;

};
DllAVIInclude.h
#pragma once

#include<iostream>
#include <time.h>
#include<cmath> 
#include <vector>  
#include <string>
#include <concurrent_queue.h>
#include <ppl.h>

#include <fstream>
DllAVIParameterDefine.h
#pragma once

#include "DllAVIInclude.h"

#define IMAGE_MAX_GV_NUM       256     //Image Max Gray Value Number
#define MAX_CONTOURS           500
DllAVIFunction.cpp
#define DLL_EXPORTS      //先定义DLL_EXPORTS,这样头文件才能被正确解析
#include "DllAVIFunction.h"


extern "C" DLL_AVI_API CAVIInterface* getInstance()
{
static CAVIFunction pInstance;
return &pInstance;
}


long CAVIFunction::mutiply(int x, int y)
{
long z = x * y;
return z;
}