中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

做網(wǎng)站公司南京關(guān)鍵詞免費(fèi)網(wǎng)站

做網(wǎng)站公司南京,關(guān)鍵詞免費(fèi)網(wǎng)站,做網(wǎng)站最好要買什么東西,武漢游戲公司本文講述C如何直接調(diào)用動(dòng)態(tài)庫dll或者so中的函數(shù)。 首先我們準(zhǔn)備一個(gè)被調(diào)用庫,這個(gè)庫里面有兩個(gè)函數(shù),分別是C98 與 C11 下的,名稱是run2和run1。 被調(diào)用庫 相關(guān)介紹請(qǐng)看之前的文章《函數(shù)指針與庫之間的通信講解》。 //dll_ex_im.h #ifndef…

本文講述C++如何直接調(diào)用動(dòng)態(tài)庫dll或者so中的函數(shù)。

首先我們準(zhǔn)備一個(gè)被調(diào)用庫,這個(gè)庫里面有兩個(gè)函數(shù),分別是C++98 與 C++11 下的,名稱是run2和run1。

被調(diào)用庫

相關(guān)介紹請(qǐng)看之前的文章《函數(shù)指針與庫之間的通信講解》。

//dll_ex_im.h
#ifndef __DLL_EX_IM_H__
#define __DLL_EX_IM_H__
#include <functional>
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#ifdef _WINDOWS
#ifdef DLLProvider
#define DLL_EXPORT_IMPORT		 __declspec(dllexport)  
#else  
#define DLL_EXPORT_IMPORT		 __declspec(dllimport)  
#endif  
#else
#define DLL_EXPORT_IMPORT __attribute__((visibility("default")))
#endif//typedef class DLL_EXPORT_IMPORT std::function< void(std::string)> output_to_caller;
DLL_EXPORT_IMPORT void run1(int a, std::function< void(std::string)> output);
DLL_EXPORT_IMPORT void run2(int a, void(*output)(std::string));#endif //__DLL_EX_IM_H__
//dll_ex_im.cpp
#include "dll_ex_im.h"void run1(int a, std::function< void(std::string)> output)
{std::cout << "run1" << std::endl;std::cout << "got parametrer: " << a << std::endl;std::cout << "return signal: " << std::endl;while (true) {output("run1: " + std::to_string(a++));std::this_thread::sleep_for(std::chrono::milliseconds(1000));}
}void run2(int a, void(*output)(std::string)) {std::cout << "run2" << std::endl;std::cout << "got parametrer: " << a << std:bian

編譯一下,出來的動(dòng)態(tài)庫在Windows下是Reflection-DLL_TEST.dll,在Linux下是libReflection-DLL_TEST.so。

Windows下直接調(diào)用

我們用BinaryViewer這款二進(jìn)制查看器看看函數(shù)run1和run2在Reflection-DLL_TEST.dll長什么樣子。

查找函數(shù)run1的位置:

找到三個(gè)位置,前兩個(gè)應(yīng)該都是函數(shù)的名稱指引(知道的同學(xué)可以介紹下前兩個(gè)是做啥的)。
第三個(gè)是run1函數(shù)的地址:
在這里插入圖片描述
我把這個(gè)run1地址寫下來:

?run1@@YAXHV?$function@$$A6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@std@@@Z

原來的函數(shù)run1長這樣:

void run1(int a, std::function< void(std::string)> output);

查找函數(shù)run2的位置:

找到三個(gè)位置,前兩個(gè)應(yīng)該都是函數(shù)的名稱指引(知道的同學(xué)可以介紹下前兩個(gè)是做啥的)。
第三個(gè)是run2函數(shù)的地址:
在這里插入圖片描述
我把這個(gè)run2地址寫下來:

?run2@@YAXHP6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@Z

原來的函數(shù)run2長這樣:

void run2(int a, void(*output)(std::string));

地址解釋

以上run1和run2函數(shù)在dll二進(jìn)制文件中的地址是一個(gè)經(jīng)過VS C++編譯器名稱修飾后的函數(shù)名,這種修飾是編譯器用來區(qū)分具有相同名稱但不同參數(shù)或返回類型的函數(shù)的方法。
由于我不是做編譯器的,下面我用聊天機(jī)器人查了一下,僅給出以上run1函數(shù)地址的解釋:
?run1@@:這是函數(shù)名run1的開頭部分,其中?和@@是Microsoft編譯器特有的名稱修飾符號(hào)。
YAXH:這表示函數(shù)的返回類型和參數(shù)類型。在這個(gè)例子中,Y 表示返回類型為 void,AX 通常表示沒有通過值傳遞的參數(shù)(但在這個(gè)特定情況下,由于后面有V,它實(shí)際上表示有一個(gè)通過引用或指針傳遞的參數(shù)),H 是參數(shù)列表的開始。不過,這里的AX和H的具體含義可能因編譯器的具體實(shí)現(xiàn)而略有不同,重要的是理解整體結(jié)構(gòu)。
V:這表示接下來的部分是一個(gè)通過引用或指針傳遞的參數(shù)。
?$function@…@std@@:這是對(duì) std::function 模板的修飾表示,其中省略號(hào)(…)代表模板參數(shù)的具體類型,即 void(std::string)。
KaTeX parse error: Can't use function '$' in math mode at position 7: A6AXV?$?basic_string@..…A6 是與調(diào)用約定相關(guān)的(可能是 __cdecl 的某種變體,但具體取決于編譯器和平臺(tái)),AXV 表示函數(shù)接受一個(gè)參數(shù)(V 表示通過引用或指針),?$basic_string@…@std@@@Z 是對(duì) std::string 類型的修飾表示。

Windows調(diào)用程序

#include <iostream>
//#include <list>
#include <functional>
#ifdef _WINDOWS 
#include <shlwapi.h>
#include <Psapi.h> 
#include <codecvt> 
#else
#include <dlfcn.h>
#include <codecvt>
#endifvoid callback(std::string info) {std::cout << info << std::endl;
}void Run1(const std::string& dllpath, const std::string& initFuncName)
{std::string funName = initFuncName;
#ifdef _WINDOWStypedef void(_stdcall* pfnInitPlugin) (int, std::function< void(std::string)>);funName = "?" + funName + "@@YAXHV?$function@$$A6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@std@@@Z";auto module = LoadLibrary(dllpath.c_str());//尋找初始化函數(shù),并執(zhí)行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常規(guī)方式//std::function< void(std::string)> cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl; });}else {std::cout << "未找到函數(shù)地址" << std::endl;}
#elsetypedef  void(__attribute__((__stdcall__))* pfnInitPlugin) (int, std::function< void(std::string));funName = "_Z22" + funName + "v";auto dp = dlopen(p.c_str(), RTLD_LAZY | RTLD_GLOBAL);if (dp){pfnInitPlugin initfunc = (pfnInitPlugin)dlsym(dp, funName.c_str());if (initfunc){initfunc(4, [](std::string info) {std::cout << info << std::endl;});}//dlclose(dp);}else {std::cout << "未找到函數(shù)地址" << std::endl;}
#endif
}void Run2(const std::string& dllpath, const std::string& initFuncName)
{std::string funName = initFuncName;
#ifdef _WINDOWStypedef void(_stdcall* pfnInitPlugin) (int, void(*output)(std::string));//run1funName = "?" + funName + "@@YAXHP6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@Z";auto module = LoadLibrary(dllpath.c_str());//尋找初始化函數(shù),并執(zhí)行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//void(*cb)(std::string);//cb = callback;//initfunc(4, cb);initfunc(4, [](std::string info) {std::cout << info << std::endl;});}else {std::cout << "未找到函數(shù)地址" << std::endl;}
#elsetypedef  void(__attribute__((__stdcall__))* pfnInitPlugin) (int, void(*output)(std::string));funName = "_Z22" + funName + "v";auto dp = dlopen(p.c_str(), RTLD_LAZY | RTLD_GLOBAL);if (dp){pfnInitPlugin initfunc = (pfnInitPlugin)dlsym(dp, funName.c_str());if (initfunc){initfunc(4, [](std::string info) {std::cout << info << std::endl;});}//dlclose(dp);}else {std::cout << "未找到函數(shù)地址" << std::endl;}
#endif
}int main(int argc, char* argv[]) {std::string argv1 = argv[1];if (argc == 2 && argv1 == "-h"){std::cout << "用法:\n【exe-name】【dll-path】【func-name】" << std::endl;return 0;}if (argc != 3){std::cerr << "傳入的參數(shù)數(shù)量不對(duì),應(yīng)該是倆,檢查檢查!!" << std::endl;return -1;}std::string dllPath = argv[1];if (dllPath.find(".dll") == dllPath.npos){std::cerr << "傳入的文件沒有dll,檢查檢查!!" << std::endl;return -1;}std::string argv2 = argv[2];if (argv2 == "run1"){Run1(argv[1], "run1");}else if (argv2 == "run2") {Run2(argv[1], "run2");}else {std::cerr << "傳入的函數(shù)名既不是 run1 也不是 run2 ,檢查檢查!!" << std::endl;return -1;}return 0;
}

在Windows下,核心代碼是下面這幾句:

	typedef void(_stdcall* pfnInitPlugin) (int, std::function< void(std::string)>);//run1funName = "?" + funName + "@@YAXHV?$function@$$A6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@std@@@Z";auto module = LoadLibrary(dllpath.c_str());//尋找初始化函數(shù),并執(zhí)行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常規(guī)方式//std::function< void(std::string)> cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl; });}else {std::cout << "未找到函數(shù)地址" << std::endl;}

程序讀入動(dòng)態(tài)庫,通過函數(shù)在動(dòng)態(tài)庫中的地址進(jìn)行直接調(diào)用。
下面是調(diào)用結(jié)果:
在這里插入圖片描述

Linux下直接調(diào)用

我們用BinaryViewer這款二進(jìn)制查看器看看函數(shù)run1和run2在libReflection-DLL_TEST.so長什么樣子。

查找函數(shù)run1的位置:

找到4個(gè)位置,前兩個(gè)應(yīng)該都是函數(shù)的名稱指引(知道的同學(xué)可以介紹下前3個(gè)是做啥的)。
第4個(gè)是run1函數(shù)的地址:
在這里插入圖片描述
我把這個(gè)run1地址寫下來:

_Z4run1iSt8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE

原來的函數(shù)run1長這樣:

void run1(int a, std::function< void(std::string)> output);

查找函數(shù)run2的位置:

找到4個(gè)位置,前兩個(gè)應(yīng)該都是函數(shù)的名稱指引(知道的同學(xué)可以介紹下前3個(gè)是做啥的)。
第4個(gè)是run2函數(shù)的地址:
在這里插入圖片描述
我把這個(gè)run2地址寫下來:

_Z4run2iPFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE

原來的函數(shù)run2長這樣:

void run2(int a, void(*output)(std::string));

地址解釋

以上run1和run2函數(shù)在so二進(jìn)制文件中的地址是一個(gè)由 GCC編譯器生成的 mangled(修飾)名稱。這種名稱用于在編譯后的代碼中唯一標(biāo)識(shí)函數(shù)、變量等符號(hào),同時(shí)包含類型信息。Mangled 名稱對(duì)于人類來說通常是不直觀的,但它們對(duì)于編譯器和鏈接器來說是必要的,以確保在復(fù)雜的程序中正確地解析和鏈接符號(hào)。
由于我不是做編譯器的,下面我用聊天機(jī)器人查了一下,僅給出以上run1函數(shù)地址的解釋:
_Z 前綴是 GCC 編譯器用于 mangled 名稱的標(biāo)識(shí)。
4run1i 部分是函數(shù)名稱的編碼,其中 run 是函數(shù)名,1 表示該函數(shù)接受一個(gè)參數(shù),i 表示該參數(shù)的類型(在這個(gè)上下文中,它實(shí)際上是指接下來的類型信息,而不是直接的類型)。
St8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE 是參數(shù)類型的 mangled 表示。這個(gè)類型是一個(gè) std::function,它包裝了一個(gè)可調(diào)用對(duì)象,該對(duì)象接受一個(gè) std::string 類型的參數(shù)(沒有返回值,因?yàn)?Fv 表示一個(gè)函數(shù)類型,沒有返回類型)。
St8function 表示 std::function。
IFv 表示一個(gè)函數(shù)(F)沒有返回值(v,即 void),并且接下來是參數(shù)類型。
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE 是 std::__cxx11::basic_string<char, std::char_traits, std::allocator> 的 mangled 表示,即 std::string。

Linux調(diào)用程序

#include <iostream>
//#include <list>
#include <functional>
#ifdef _WINDOWS 
#include <shlwapi.h>
#include <Psapi.h> 
#include <codecvt> 
#else
#include <dlfcn.h>
#include <codecvt>
#endifvoid callback(std::string info) {std::cout << info << std::endl;
}void Run1(const std::string& dllpath, const std::string& initFuncName)
{std::string funName = initFuncName;
#ifdef _WINDOWStypedef void(_stdcall* pfnInitPlugin) (int, std::function< void(std::string)>);funName = "?" + funName + "@@YAXHV?$function@$$A6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@std@@@Z";auto module = LoadLibrary(dllpath.c_str());//尋找初始化函數(shù),并執(zhí)行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常規(guī)方式//std::function< void(std::string)> cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl; });}else{std::cout<<"not find function name"<<std::endl;}
#elsetypedef  void(* pfnInitPlugin) (int, std::function< void(std::string)>);funName = "_Z4" + funName + "iSt8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE";auto dp = dlopen(dllpath.c_str(), RTLD_LAZY | RTLD_GLOBAL);if (dp){pfnInitPlugin initfunc = (pfnInitPlugin)dlsym(dp, funName.c_str());if (initfunc){initfunc(4, [](std::string info) {std::cout << info << std::endl;});}dlclose(dp);}else{std::cout<<"not find function name"<<std::endl;}
#endif
}void Run2(const std::string& dllpath, const std::string& initFuncName)
{std::string funName = initFuncName;
#ifdef _WINDOWStypedef void(_stdcall* pfnInitPlugin) (int, void(*output)(std::string));funName = "?" + funName + "@@YAXHP6AXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z@Z";auto module = LoadLibrary(dllpath.c_str());//尋找初始化函數(shù),并執(zhí)行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常規(guī)方式//void(*cb)(std::string);//cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl;});}else{std::cout<<"not find function name"<<std::endl;}
#elsetypedef  void(* pfnInitPlugin) (int, void(*output)(std::string));funName = "_Z4" + funName + "iPFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE";auto dp = dlopen(dllpath.c_str(), RTLD_LAZY | RTLD_GLOBAL);if (dp){pfnInitPlugin initfunc = (pfnInitPlugin)dlsym(dp, funName.c_str());if (initfunc){initfunc(4, [](std::string info) {std::cout << info << std::endl;});}dlclose(dp);}else{std::cout<<"not find function name"<<std::endl;}
#endif
}int main(int argc, char* argv[]) {//C++ 98//Lambda回調(diào)函數(shù)//Run1("./Reflection-DLL_TEST.dll","run1");std::string argv1 = argv[1];if (argc == 2 && argv1 == "-h"){std::cout << "用法:\n【exe-name】【dll-path】【func-name】" << std::endl;return 0;}if (argc != 3){std::cerr << "傳入的參數(shù)數(shù)量不對(duì),應(yīng)該是倆,檢查檢查!!" << std::endl;return -1;}std::string dllPath = argv[1];if (dllPath.find(".so") == dllPath.npos){std::cerr << "傳入的文件沒有so,檢查檢查!!" << std::endl;return -1;}std::string argv2 = argv[2];if (argv2 == "run1"){Run1(argv[1], "run1");}else if (argv2 == "run2") {Run2(argv[1], "run2");}else {std::cerr << "傳入的函數(shù)名既不是 run1 也不是 run2 ,檢查檢查!!" << std::endl;return -1;}//system("pause");return 0;
}

在Linux下,核心代碼是下面這幾句:

	typedef  void(* pfnInitPlugin) (int, std::function< void(std::string)>);funName = "_Z4" + funName + "iSt8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE";auto dp = dlopen(dllpath.c_str(), RTLD_LAZY | RTLD_GLOBAL);if (dp){pfnInitPlugin initfunc = (pfnInitPlugin)dlsym(dp, funName.c_str());if (initfunc){initfunc(4, [](std::string info) {std::cout << info << std::endl;});}dlclose(dp);}else{std::cout<<"not find function name"<<std::endl;}

程序讀入動(dòng)態(tài)庫,通過函數(shù)在動(dòng)態(tài)庫中的地址進(jìn)行直接調(diào)用。
下面是調(diào)用結(jié)果:
在這里插入圖片描述

http://www.risenshineclean.com/news/33318.html

相關(guān)文章:

  • c 做網(wǎng)站設(shè)計(jì)關(guān)鍵詞排名提高方法
  • pageadmin如何做網(wǎng)站數(shù)據(jù)分析培訓(xùn)班
  • 代還信用卡網(wǎng)站建設(shè)國內(nèi)最新十大新聞
  • .net mvc做網(wǎng)站一鍵優(yōu)化清理
  • 單縣網(wǎng)站定制網(wǎng)絡(luò)營銷策劃的主要特點(diǎn)
  • 國外網(wǎng)站 服務(wù)器青島seo排名公司
  • 網(wǎng)頁即時(shí)聊天seo推廣怎么樣
  • 用動(dòng)物做網(wǎng)站名稱可以投放廣告的網(wǎng)站
  • 沒有備案的網(wǎng)站可以做淘寶客seo網(wǎng)絡(luò)推廣培訓(xùn)班
  • 校園論壇網(wǎng)站怎么做谷歌收錄提交入口
  • 長沙岳麓區(qū)做網(wǎng)站seo內(nèi)容優(yōu)化是什么
  • 怎么做網(wǎng)站首頁全媒體廣告代理
  • 去國外做移動(dòng)支付網(wǎng)站嗎廣告投放網(wǎng)站
  • 四川網(wǎng)站建設(shè)一站式服務(wù)商互聯(lián)網(wǎng)公司網(wǎng)站模板
  • 企業(yè)oa系統(tǒng)免費(fèi)優(yōu)化網(wǎng)站建設(shè)seo
  • 淘寶做個(gè)網(wǎng)站多少錢seo概念
  • 一級(jí)a做爰片免費(fèi)無碼網(wǎng)站網(wǎng)絡(luò)流量分析工具
  • php網(wǎng)站開發(fā)百度云產(chǎn)品推廣計(jì)劃方案
  • 網(wǎng)站對(duì)比app還有優(yōu)勢嗎2023第三波疫情已經(jīng)到來了
  • 網(wǎng)站空間多久續(xù)一次費(fèi)seo優(yōu)化團(tuán)隊(duì)
  • 鎮(zhèn)江外貿(mào)網(wǎng)站建設(shè)站外推廣渠道有哪些
  • Axure只是做網(wǎng)站嗎怎么注冊一個(gè)自己的網(wǎng)址
  • 湛江自做網(wǎng)站杭州谷歌推廣
  • 河南科興建設(shè)有限公司網(wǎng)站網(wǎng)站推廣公司黃頁
  • 石家莊專業(yè)商城網(wǎng)站制作百度如何優(yōu)化
  • 用身份證備案網(wǎng)站外貿(mào)營銷渠道
  • 天津市建設(shè)工程評(píng)標(biāo)專家網(wǎng)站谷歌google官網(wǎng)下載
  • 為什么登錄不上建設(shè)銀行網(wǎng)站上海網(wǎng)站建設(shè)推廣服務(wù)
  • 蒼南龍港做網(wǎng)站店鋪亞馬遜免費(fèi)的關(guān)鍵詞工具
  • 網(wǎng)站建設(shè)與網(wǎng)頁制作技術(shù)拉新項(xiàng)目官方一手平臺(tái)