当前位置: 首页 > news >正文

眉山建设中等职业技术学校 网站推广策略都有哪些

眉山建设中等职业技术学校 网站,推广策略都有哪些,做会计网站的流程图,wordpress 中文模块本文讲述C如何直接调用动态库dll或者so中的函数。 首先我们准备一个被调用库,这个库里面有两个函数,分别是C98 与 C11 下的,名称是run2和run1。 被调用库 相关介绍请看之前的文章《函数指针与库之间的通信讲解》。 //dll_ex_im.h #ifndef…

本文讲述C++如何直接调用动态库dll或者so中的函数。

首先我们准备一个被调用库,这个库里面有两个函数,分别是C++98 与 C++11 下的,名称是run2和run1。

被调用库

相关介绍请看之前的文章《函数指针与库之间的通信讲解》。

//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

编译一下,出来的动态库在Windows下是Reflection-DLL_TEST.dll,在Linux下是libReflection-DLL_TEST.so。

Windows下直接调用

我们用BinaryViewer这款二进制查看器看看函数run1和run2在Reflection-DLL_TEST.dll长什么样子。

查找函数run1的位置:

找到三个位置,前两个应该都是函数的名称指引(知道的同学可以介绍下前两个是做啥的)。
第三个是run1函数的地址:
在这里插入图片描述
我把这个run1地址写下来:

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

原来的函数run1长这样:

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

查找函数run2的位置:

找到三个位置,前两个应该都是函数的名称指引(知道的同学可以介绍下前两个是做啥的)。
第三个是run2函数的地址:
在这里插入图片描述
我把这个run2地址写下来:

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

原来的函数run2长这样:

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

地址解释

以上run1和run2函数在dll二进制文件中的地址是一个经过VS C++编译器名称修饰后的函数名,这种修饰是编译器用来区分具有相同名称但不同参数或返回类型的函数的方法。
由于我不是做编译器的,下面我用聊天机器人查了一下,仅给出以上run1函数地址的解释:
?run1@@:这是函数名run1的开头部分,其中?和@@是Microsoft编译器特有的名称修饰符号。
YAXH:这表示函数的返回类型和参数类型。在这个例子中,Y 表示返回类型为 void,AX 通常表示没有通过值传递的参数(但在这个特定情况下,由于后面有V,它实际上表示有一个通过引用或指针传递的参数),H 是参数列表的开始。不过,这里的AX和H的具体含义可能因编译器的具体实现而略有不同,重要的是理解整体结构。
V:这表示接下来的部分是一个通过引用或指针传递的参数。
?$function@…@std@@:这是对 std::function 模板的修饰表示,其中省略号(…)代表模板参数的具体类型,即 void(std::string)。
KaTeX parse error: Can't use function '$' in math mode at position 7: A6AXV?$̲basic_string@..…A6 是与调用约定相关的(可能是 __cdecl 的某种变体,但具体取决于编译器和平台),AXV 表示函数接受一个参数(V 表示通过引用或指针),?$basic_string@…@std@@@Z 是对 std::string 类型的修饰表示。

Windows调用程序

#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());//寻找初始化函数,并执行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常规方式//std::function< void(std::string)> cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl; });}else {std::cout << "未找到函数地址" << 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 << "未找到函数地址" << 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());//寻找初始化函数,并执行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 << "未找到函数地址" << 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 << "未找到函数地址" << 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 << "传入的参数数量不对,应该是俩,检查检查!!" << 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 << "传入的函数名既不是 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());//寻找初始化函数,并执行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常规方式//std::function< void(std::string)> cb = callback;//initfunc(4, cb);//lambda方式initfunc(4, [](std::string info) {std::cout << info << std::endl; });}else {std::cout << "未找到函数地址" << std::endl;}

程序读入动态库,通过函数在动态库中的地址进行直接调用。
下面是调用结果:
在这里插入图片描述

Linux下直接调用

我们用BinaryViewer这款二进制查看器看看函数run1和run2在libReflection-DLL_TEST.so长什么样子。

查找函数run1的位置:

找到4个位置,前两个应该都是函数的名称指引(知道的同学可以介绍下前3个是做啥的)。
第4个是run1函数的地址:
在这里插入图片描述
我把这个run1地址写下来:

_Z4run1iSt8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE

原来的函数run1长这样:

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

查找函数run2的位置:

找到4个位置,前两个应该都是函数的名称指引(知道的同学可以介绍下前3个是做啥的)。
第4个是run2函数的地址:
在这里插入图片描述
我把这个run2地址写下来:

_Z4run2iPFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE

原来的函数run2长这样:

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

地址解释

以上run1和run2函数在so二进制文件中的地址是一个由 GCC编译器生成的 mangled(修饰)名称。这种名称用于在编译后的代码中唯一标识函数、变量等符号,同时包含类型信息。Mangled 名称对于人类来说通常是不直观的,但它们对于编译器和链接器来说是必要的,以确保在复杂的程序中正确地解析和链接符号。
由于我不是做编译器的,下面我用聊天机器人查了一下,仅给出以上run1函数地址的解释:
_Z 前缀是 GCC 编译器用于 mangled 名称的标识。
4run1i 部分是函数名称的编码,其中 run 是函数名,1 表示该函数接受一个参数,i 表示该参数的类型(在这个上下文中,它实际上是指接下来的类型信息,而不是直接的类型)。
St8functionIFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE 是参数类型的 mangled 表示。这个类型是一个 std::function,它包装了一个可调用对象,该对象接受一个 std::string 类型的参数(没有返回值,因为 Fv 表示一个函数类型,没有返回类型)。
St8function 表示 std::function。
IFv 表示一个函数(F)没有返回值(v,即 void),并且接下来是参数类型。
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE 是 std::__cxx11::basic_string<char, std::char_traits, std::allocator> 的 mangled 表示,即 std::string。

Linux调用程序

#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());//寻找初始化函数,并执行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常规方式//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());//寻找初始化函数,并执行pfnInitPlugin initfunc = (pfnInitPlugin)GetProcAddress(module, funName.c_str());if (initfunc){//常规方式//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回调函数//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 << "传入的参数数量不对,应该是俩,检查检查!!" << 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 << "传入的函数名既不是 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;}

程序读入动态库,通过函数在动态库中的地址进行直接调用。
下面是调用结果:
在这里插入图片描述

http://www.fp688.cn/news/160978.html

相关文章:

  • 网络网页设计师郑州seo顾问
  • 做网站用什么云服务器吗促销活动推广语言
  • 什么公司在百度做网站网络推广渠道
  • 制作企业网站公司排名抖音seo源码搭建
  • 代做网站毕业设计长沙企业关键词优化
  • 需要做网站的企业电话中国网站排名100
  • 网站建设制作要学什么关键词指数
  • 做视频网站 买带宽b站推广网站2022
  • 一级做ae视频直播可以吗多少钱群排名优化软件官网
  • 龙岩做网站开发哪家做的好网络营销十大成功案例
  • 做直播网站需要手续关键词分类
  • 海淀区企业网站建设seo是什么意思怎么解决
  • h5响应式网站做动画企业网页设计制作
  • 做网站哪家好 张家口游戏推广公司
  • 制作一个网站界面设计图片好看的网站模板
  • 如何入侵网站服务器网站制作公司排行榜
  • 网站建设委托合同搜索引擎的优化方法有哪些
  • 云南网站建设维修公司百度推广登录后台
  • 日本做电子贺卡网站企业中层管理人员培训课程
  • 一些简约大气的网站网络品牌营销
  • 大连地区做网站全网优化哪家好
  • 网站上做皮肤测试上海网站推广系统
  • 一个网站主机多少钱百度关键词热度排名
  • 房地产网站模板 下载深圳发布最新通告
  • 模板网站有什么不好重庆seo网站
  • 在网站开发中进行用户管理站点搜索
  • 青岛出版集团网站珠海网站设计
  • 淘宝客网站源码html做网页用什么软件好
  • 福州网站建设 联系yanktcn 04娃哈哈软文推广
  • 兰州网站建设方案百度竞价广告的位置