C++deDLL的制作
1、首先是头文件
#pragma once
#ifndef _ANIMAL_H
#define _ANIMAL_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef DLLCLASS_EXPORTS
#define CREATEANIMALDLL_API_DU _declspec(dllexport)
#else
#define CREATEANIMALDLL_API_DU _declspec(dllimport) //当编译时,头文件不参加编译,所以.cpp文件中先定义,后头文件被包含进来,因此外部使用时,为dllexport,而在内部编译时,则为dllimport
#endif
class CREATEANIMALDLL_API_DU animal //需要被外界调用的类(父类)
{
public:
virtual int outDate() = 0; //纯虚函数
void getWide(int x) ;
void getHigh(int y) ;
protected:
int wide;
int high;
};
class CREATEANIMALDLL_API_DU cat :public animal //需要被调用的类(子类cat)
{
public:
int outDate();
};
class CREATEANIMALDLL_API_DU dog :public animal //需要被调用的类(子类dog)
{
public:
int outDate();
void getWide(int x);
void getHigh(int y);
};
int CREATEANIMALDLL_API_DU exportDate(); //需要被调用的函数(单独的一个函数,不属于任何一个类)
int CREATEANIMALDLL_API_DU add(int a, int b);
int CREATEANIMALDLL_API_DU ptr_dog(dog** Dog);
int CREATEANIMALDLL_API_DU Mes_add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
extern "C"是必须要加的否则编译出来的dll库,使用动态调用时是识别不到函数的,原因是C++和C语言在生成dll库时的函数名是不一定相同的
2、源文件(函数接口的实现以及如何调用C#Com口的接口)
#include "pch.h"
#include <iostream>
#define DLLCLASS_EXPORTS
#include "animal.h"
using namespace std;
//父类中函数实现
void CREATEANIMALDLL_API_DU animal::getWide(int x) {
wide = x;
}
void CREATEANIMALDLL_API_DU animal::getHigh(int y) {
high = y;
}//子类cat中数据输出实现
int CREATEANIMALDLL_API_DU cat::outDate() {
return (wide + high);
}//子类dog数据输出实现
int CREATEANIMALDLL_API_DU dog::outDate() {
return (wide - high);
}//函数的实现
void CREATEANIMALDLL_API_DU dog::getWide(int x) {
wide = x;
}
void CREATEANIMALDLL_API_DU dog::getHigh(int y) {
high = y;
}//子类cat中数据输出实现
int CREATEANIMALDLL_API_DU exportDate() {
return 666;
}
int CREATEANIMALDLL_API_DU add(int a,int b)
{
return a + b;
}
int CREATEANIMALDLL_API_DU ptr_dog(dog** Dog)
{
*Dog = new dog();
return 0;
}
extern int Add(int a, int b);
int CREATEANIMALDLL_API_DU Mes_add(int a, int b)
{
return Add(a, b);
}
在动态生成调用DLL时,注意指针接口只能只想从父类继承并实现的虚函数,以及自己的新增的函数,无法指向父类函数,否则编译时会出问题。
#include "pch.h"
#include <iostream>
//#include <atlstr.h>
#import "../Mes/Mes.tlb"
class MesInterface
{
public:
MesInterface()
{
CoInitialize(NULL);
mHr = mPtr.CreateInstance(__uuidof (Mes::EiotMes));
if (mHr != S_OK)
{
//::AfxMessageBox("请注册组件!", 0);
MessageBoxA(NULL,"请注册组件!", 0, MB_OK);
}
}
~MesInterface()
{
CoUninitialize();
}
int Add(int x, int y)
{
if (mHr == S_OK)
{
return mPtr->Add(x, y);
}
return -1;
}
private:
HRESULT mHr;
Mes::IMesInterfacePtr mPtr;
};
int Add(int a, int b)
{
MesInterface mes;
return mes.Add(a, b);
}
//#using "../Mes/Mes.dll"
环境配置
一般包含一下C#生成com口tlb文件的接口就行
如何调用
静态调用时包含头文件以及环境配置如下
头文件同上
环境配置如下
动态调用时不需要配置文件
调用的.c 文件
#include <iostream>
#include "animal.h"
#include<windows.h>
using namespace std;
#pragma comment(lib, "MakeDll_Cplus.lib")
int main()
{
//dll的
{
cout << exportDate() << endl; //调用函数输出666
dog DOG; //实例化dog对象、赋值、并输出。
DOG.getHigh(5);
DOG.getWide(6);
cout << DOG.outDate() << endl;
cat CAT; //实例化cat对象、赋值、并输出
CAT.getHigh(16);
CAT.getWide(4);
cout << CAT.outDate() << endl;
std::cout << Mes_add(1, 10) << std::endl;
}
HMODULE module = LoadLibraryA("MakeDll_Cplus.dll"); // 根据DLL文件名,加载DLL,返回一个模块句柄
if (module == NULL)
{
printf("加载DLLTest1.dll动态库失败\n");
return 0;
}
typedef int(*Mes_add)(int,int);
Mes_add Mes_Add;
Mes_Add = (Mes_add)GetProcAddress(module, "add");
std::cout << Mes_Add(1, 10) << std::endl;
typedef int(*AddFunc)(int,int);
AddFunc add1;
add1 = (AddFunc)GetProcAddress(module, "add");
if (add1 == NULL)
{
std::cout << "GetProcAddress(module, \"add\") fail\n" << endl;
return 0;
}
std::cout << add1(1,2) << endl;
typedef int(*ExportDate)();
ExportDate ExportDate1;
ExportDate1 = (ExportDate)GetProcAddress(module, "exportDate");
if (ExportDate1 == NULL)
{
std::cout << "GetProcAddress(module, \"exportDate\") fail\n" << endl;
return 0;
}
std::cout << ExportDate1() << endl;
typedef int (*Ptr_dog)(dog** ptr_dog);
Ptr_dog ptr_dog;
dog* Dog = NULL;
ptr_dog = (Ptr_dog)GetProcAddress(module, "ptr_dog");
if (ptr_dog == NULL)
{
std::cout << "GetProcAddress(module, \"ptr_dog\") fail\n";
return 0;
}
ptr_dog(&Dog);
cout<< Dog->outDate()<<endl;
if (module != NULL)
{
FreeLibrary(module);
module = NULL;
}
std::cout << "Hello World!\n";
return 0;
}