1、首先,建立一个项目,注意要勾选 动态链接库(DLL)。
fun.h, 定义需要给外部调用的函数
#pragma once
#include<string>
#include<iostream>
#define FUN_API _declspec(dllexport)
EXTERN_C FUN_API int fun1(int a, int &b, std::string c);
fun.cpp
// fun_dll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "fun_dll.h"
FUN_API int fun1(int a, int & b, std::string c)
{
std::cout << "fun1 load succeed!" << std::endl;
//return FUN_API int();
a++;
b++;
std::cout << "a=\t" << a << std::endl;
std::cout << "b=\t" << b << std::endl;
std::cout << "c=\t" << c << std::endl;
return 1;
}
编译 准备好dll。
2、新建项目,加载dlll
#include<windows.h>
using namespace std;
static HINSTANCE hDllInst = NULL;
int init(void)
{
// Way1 use LoadLibraryEx( ) and obsolute dir to laod DLL
//hDllInst = LoadLibraryEx(_T("D:\\TEST\\x64\\Release\\fun.dll"),NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
Way2
//TCHAR chCurDir[MAX_PATH] = { 0 };
//GetCurrentDirectory(MAX_PATH, chCurDir); // save current dir for main-exe
//SetCurrentDirectory(_T("..\\..\\TEST\\x64\\Release\\")); // jump to dir for dll
//hDllInst = LoadLibrary(_T("fun.dll")); //load DLL in dir for dll
//SetCurrentDirectory(chCurDir); //jump back to current dir
hDllInst = LoadLibrary(_T("fun.dll"));
if (hDllInst == NULL)
{
printf("loading fun.dll failed: %d\r\n", GetLastError());
return -1;
}
return 0;
}
int point_cloud_calc_deinit(void)
{
FreeLibrary(hDllInst);
return 0;
}
3、取出dll中 对应的函数
// Dll_usage.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include<Windows.h>
#include<tchar.h>
static HINSTANCE dll_init = NULL;
int initial_dll() {
Way1 use LoadLibraryEx( ) and obsolute dir to laod DLL
//dll_init = LoadLibraryEx(_T("D:\\fun_dll\\x64\\Release\\PC_calc.dll"),NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
// Way2
TCHAR chCurDir[MAX_PATH] = { 0 };
GetCurrentDirectory(MAX_PATH, chCurDir); // save current dir for main-exe
SetCurrentDirectory(_T("..\\..\\fun_dll\\x64\\Release\\")); // jump to dir for dll
dll_init = LoadLibrary(_T("fun_dll.dll")); //load DLL in dir for dll
SetCurrentDirectory(chCurDir); //jump back to current dir
Way3
//dll_init = LoadLibrary(_T("fun_dll.dll"));
//if (dll_init == NULL){
// printf("loading fun_dll.dll failed: %d\r\n", GetLastError());
// return -1;
//}
return 0;
}
int fun1(int a, int &b, std::string c) {
typedef int(WINAPI *pDll)(int a, int & b, std::string c); //根据函数实际的返回值来
pDll p_dll = NULL;
p_dll = (pDll)GetProcAddress(dll_init, "fun1");
if (p_dll) {
return p_dll(a, b, c);
}
else {
std::cout << "Loading fun1 failed!" << std::endl;
return -1;
}
}
int main()
{
initial_dll();
int a = 1, b = 2;
std::string c = "quelquefois";
int res = fun1(1, b, c);
std::cout << "fun1()=" << res << std::endl;
std::cout << "Hello World!\n";
}
即可调用。
结果发现 string并没有传递到dll函数中。
常见问题:
1、跨目录调用 找不到dll
2、调用dll中的函数,无法传递string类型
解决方法一:改用char*,因为dll的接口使用的是c的那一套,加入c++的东西(例如string),不兼容。但这也反应了语言的缺陷。要么不能用string,使用后直接报错。
修改dll中函数定义 如下:
//FUN_API int fun1(int a, int & b, std::string c)
FUN_API int fun1(int a, int & b, char* c)
int main()
{
initial_dll();
int a = 1, b = 2;
//std::string c = "quelquefois";
char c[] = "quelquefois";
int res = fun1(1, b, c);
std::cout << "fun1()=" << res << std::endl;
std::cout << "Hello World!\n";
}
这下得到了预期的结果了。
进阶:最近想在dll中实现函数重载,查阅了很多资料,没有找到很方便的方法。在普通的c++中函数重载是很容易的事情,折腾了一中午,决定放弃在dll中弄重载。
关于 extern “C”:若使用extern “C”,则函数名称保持不变,调用较方便,但是不支持函数重载等一系列c++功能;若不使用extern “C”,则调用前要查看编译后的符号,非常不方便。
dll更多说明参考:
http://www.cnblogs.com/findumars/p/5636506.html
dll函数重载,这种并不是我想要的,反而更加麻烦了你说是不是==
https://www.xuebuyuan.com/643161.html
对了,有个思路是 封装成类,再导出dll,这样就可以在dll中实现函数重载了,等我有空了再来试试