C++函数的导出与导入
DLL使用
(1)隐式链接到 DLL 的可运行文件在生成时链接到导入库(.lib文件)。
(2)採用显式连接(LoadLibrary和GetProcAddress)时,不须要.lib文件。
函数导出方式
(1)源码中的 __declspec(dllexport) keyword
(2).def 文件里的 EXPORTS 语句
(3)LINK 命令中的 /EXPORT 规范
全部这三种方法能够用在同一个程序中。
LINK 在生成包括导出的程序时还创建导入库,除非生成中使用了 .exp 文件。
导出
CppDynamicLinkLibrary.cpp
#include "CppDynamicLinkLibrary.h"
#include <strsafe.h> #pragma region DLLMain
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#pragma endregion #pragma region Global Data // An exported/imported global data using a DEF file
// Initialize it to be 1
int g_nVal1 = 1; // An exported/imported global data using __declspec(dllexport/dllimport)
// Initialize it to be 2
SYMBOL_DECLSPEC int g_nVal2 = 2; #pragma endregion #pragma region Ordinary Functions // An exported/imported cdecl(default) function using a DEF file
int /*__cdecl*/ GetStringLength1(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
} // An exported/imported stdcall function using __declspec(dllexport/dllimport)
SYMBOL_DECLSPEC int __stdcall GetStringLength2(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
} #pragma endregion #pragma region Callback Function // An exported/imported stdcall function using a DEF file
// It requires a callback function as one of the arguments
int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc)
{
// Make the callback to the comparison function // If a is greater than b, return a;
// If b is greater than or equal to a, return b.
return ((*cmpFunc)(a, b) > 0) ? a : b;
} #pragma endregion #pragma region Class // Constructor of the simple C++ class
CSimpleObject::CSimpleObject(void) : m_fField(0.0f)
{
} // Destructor of the simple C++ class
CSimpleObject::~CSimpleObject(void)
{
} float CSimpleObject::get_FloatProperty(void)
{
return this->m_fField;
} void CSimpleObject::set_FloatProperty(float newVal)
{
this->m_fField = newVal;
} HRESULT CSimpleObject::ToString(PWSTR pszBuffer, DWORD dwSize)
{
return StringCchPrintf(pszBuffer, dwSize, L"%.2f", this->m_fField);
} int CSimpleObject::GetStringLength(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
} #pragma endregion
CppDynamicLinkLibrary.def
LIBRARY CppDynamicLinkLibrary
EXPORTS
GetStringLength1 @1
CompareInts @2
g_nVal1 DATA
导入
CppLoadLibrary.cpp
#pragma region Includes
#include <stdio.h>
#include <windows.h>
#pragma endregion // Function pointer types for functions exported from the DLL module typedef int (_cdecl* LPFNGETSTRINGLENGTH1) (PCWSTR); // CALLBACK, aka __stdcall, can only be used for stdcall methods. If it is
// used for __cdecl methods, this error will be thrown in runtime: The value
// of ESP was not properly saved across a function call. This is usually a
// result of calling a function declared with one calling convention with a
// function pointer declared with a different calling convention.
typedef int (CALLBACK* LPFNGETSTRINGLENGTH2) (PCWSTR); // Type-definition of the 'PFN_COMPARE' callback function, and the CompareInts
// function that requires the callback as one of the arguments.
typedef int (CALLBACK* PFN_COMPARE) (int, int);
typedef int (CALLBACK* LPFNMAX) (int, int, PFN_COMPARE); //
// FUNCTION: IsModuleLoaded(PCWSTR)
//
// PURPOSE: Check whether or not the specified module is loaded in the
// current process.
//
// PARAMETERS:
// * pszModuleName - the module name
//
// RETURN VALUE: The function returns TRUE if the specified module is
// loaded in the current process. If the module is not loaded, the function
// returns FALSE.
//
BOOL IsModuleLoaded(PCWSTR pszModuleName)
{
// Get the module in the process according to the module name.
HMODULE hMod = GetModuleHandle(pszModuleName);
return (hMod != NULL);
} //
// FUNCTION: Max(int, int)
//
// PURPOSE: This is the callback function for the method Max exported from
// CppDynamicLinkLibrary.dll
//
// PARAMETERS:
// * a - the first integer
// * b - the second integer
//
// RETURN VALUE: The function returns a positive number if a > b, returns 0
// if a equals b, and returns a negative number if a < b.
//
int CALLBACK Max(int a, int b)
{
return (a - b);
} int wmain(int argc, wchar_t *argv[])
{
BOOL fLoaded = FALSE;
HINSTANCE hModule = NULL; // The name of the module to be dynamically-loaded.
PCWSTR pszModuleName = L"CppDynamicLinkLibrary"; // Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not "); // Dynamically load the library.
wprintf(L"Load the library\n");
hModule = LoadLibrary(pszModuleName);
if (hModule == NULL)
{
wprintf(L"LoadLibrary failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
} // Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not "); //
// Access the global data exported from a module.
// // Dynamically-loaded DLL does not allow you to access the global data
// exported from the DLL. //
// Call the functions exported from a module.
// PCWSTR pszString = L"HelloWorld";
int nLength; // Call int /*__cdecl*/ GetStringLength1(PWSTR pszString);
LPFNGETSTRINGLENGTH1 lpfnGetStringLength1 = (LPFNGETSTRINGLENGTH1)GetProcAddress(hModule, "GetStringLength1");
if (lpfnGetStringLength1 == NULL)
{
wprintf(L"GetStringLength1 cannot be found (Error: 0x%08lx)\n",
GetLastError());
goto Cleanup;
}
nLength = lpfnGetStringLength1(pszString);
wprintf(L"Function: GetStringLength1(\"%s\") => %d\n", pszString, nLength); // Call int __stdcall GetStringLength2(PWSTR pszString);
LPFNGETSTRINGLENGTH2 lpfnGetStringLength2 = (LPFNGETSTRINGLENGTH2)GetProcAddress(hModule, "_GetStringLength2@4");
if (lpfnGetStringLength2 == NULL)
{
wprintf(L"GetStringLength2 cannot be found (Error: 0x%08lx)\n",
GetLastError());
goto Cleanup;
}
nLength = lpfnGetStringLength2(pszString);
wprintf(L"Function: GetStringLength2(\"%s\") => %d\n", pszString, nLength); //
// Call the callback functions exported from a module.
// // Call int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc);
LPFNMAX lpfnMax = (LPFNMAX)GetProcAddress(hModule, "CompareInts");
if (lpfnMax == NULL)
{
wprintf(L"CompareInts cannot be found (Error: 0x%08lx)\n", GetLastError());
goto Cleanup;
}
int max = lpfnMax(2, 3, &Max);
wprintf(L"Function: CompareInts(2, 3,Max) => %d\n", max); //
// Use the class exported from a module.
// // Dynamically-loaded DLL does not allow you to use the class exported
// from the DLL. Cleanup: if (hModule)
{
// Attempt to free and unload the library.
wprintf(L"Unload the dynamically-loaded DLL\n");
if (!FreeLibrary(hModule))
{
wprintf(L"FreeLibrary failed w/err 0x%08lx\n", GetLastError());
}
} // Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not "); return 0;
}
演示样例project地址:http://download.csdn.net/detail/x356982611/8071757
C++函数的导出与导入的更多相关文章
- ES5和ES6对象导出和导入(转载,待整理)
1.import ... form...替代 require() //不接收对象 require:require('s.css'); //(es5) improt 's.css' //(es6) // ...
- Oracle简单的备份和恢复-导出和导入(1)
ylbtech-Oracle:Oracle简单的备份和恢复-导出和导入(1) Oracle简单的备份和恢复-导出和导入 1. 用户导出自己的表(emp,dept)返回顶部 1.1, 我们启动Oracl ...
- Oracle简单的备份和恢复-导出和导入(2)
ylbtech-Oracle:Oracle简单的备份和恢复-导出和导入(2) 简单的备份和恢复-导出和导入(2) 1. 用户导入导出文件中的一张表(emp)返回顶部 0.1, 我们在sql plus中 ...
- windows下 Mysql 8.0.x 数据库简单的导出和导入!!!
1.首先需要进入到mysql安装目录下的bin目录,执行cmd进入命令窗口. 2.导出(导出某个数据库,也可以针对某张表导出)2.1导出数据结构以及数据的命令: mysqldump -u root - ...
- [moka同学笔记]PHPexcel之excel导出和导入
原案例来自http://www.sucaihuo.com/有修改 1.目录结构(文件不用解释,应该都可以看得懂,直接看代码)
- ORACLE 导出(exp) & 导入(imp)
导出(exp) & 导入(imp) 利用Export可将数据从数据库中提取出来,就是将select的结果存到一个FS二进制文件上 利用Import则可将提取出来的数据送回到Ora ...
- OCR磁盘的导出和导入、备份和恢复以及移动(ocrconfig命令的应用)
数据库版本:10.2.0.1 一,使用导出.导入进行备份和恢复 Oracle推荐在对集群做调整时,比如增加.删除节点之前,应该对OCR做一个备份,可以使用export 备份到指定文件.如果做了repl ...
- paip 自定义输入法多多输入法词库的备份导出以及导入
paip 自定义输入法词库的备份导出以及导入 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/ ...
- mysql如何利用Navicat 导出和导入数据库
MySql是我们经常用到的数据,无论是开发人员用来练习,还是小型私服游戏服务器,或者是个人软件使用,都十分方便.对于做一些个人辅助软件, 选择mysql数据库是个明智的选择,有一个好的工具更是事半功倍 ...
随机推荐
- Java泛型(一):入门、原理、使用
远在 JDK 1.4 版本的时候,那时候是没有泛型的概念的.当时 Java 程序员们写集合类的代码都是类似于下面这样: List list = new ArrayList(); list.add(&q ...
- uva 10061(数学)
题解:题目要在b进制下输出的是一个数字阶乘后有多少个零,然后输出一共同拥有多少位.首先计算位数,log(n)/log(b) + 1就是n在b进制下有多少位,而log有个公式就是log(M×N) = l ...
- java 线程 生产者-消费者与队列,任务间使用管道进行输入、输出 解说演示样例 --thinking java4
package org.rui.thread.block2; import java.io.BufferedReader; import java.io.IOException; import jav ...
- unity3D游戏开发实战原创视频讲座系列9之塔防类游戏开发第一季
解说文件夹 塔防游戏0基础篇... 第一讲 游戏演示和资源介绍... 第二讲 游戏场景的完毕... 第三讲 预制体的制作... 第四讲 敌人的随机产生和按路径行走... 第五讲 塔防工具的产 ...
- idea使用技巧资料篇
基本使用:https://my.oschina.net/lujianing/blog/177042#OSC_h1_2 解决idea卡顿问题:http://www.cnblogs.com/ae6623/ ...
- 0x35 高斯消元与线性空间
颓了十天回来做题果然…… 感觉还是很有收获的,这两以前都没学过 bzoj1013: [JSOI2008]球形空间产生器sphere poj1830(upd) 之前做得很烂还被 D飞*2 了..重做一次 ...
- ASP.NET Core-组件-后台任务:Hangfire
ylbtech-ASP.NET Core-组件-后台任务:Hangfire Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库.在.net core的环境中,由Core自带的 ...
- Windows远程桌面和360
Windows的远程桌面输错了一次密码, 然后就怎么都连接不上了, 查了半天发现 傻缺360会默认屏蔽Windows的远程桌面和数据库连接..... 大家没事都卸载了360吧
- Redis学习笔记(三) 基本命令:Key操作
参考:http://doc.redisfans.com/ del key 删除给定的一个或多个Key(多个key用空格隔开),删除成功返回1,当key不存在时,返回0:例:del no-exist-k ...
- maridb Error 'Operation DROP USER failed for
数据库版本:mariadb 10.0.12 主库删除多余的用户名,因从库没有此信息造成主从故障! 报错信息如下:Error 'Operation DROP USER failed for 'use ...