首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何从可执行文件中调用动态链接库的虚函数?C++ VS2019

在C++中,从可执行文件中调用动态链接库(DLL)的虚函数涉及到几个关键步骤。以下是详细的解释和示例代码。

基础概念

  1. 动态链接库(DLL):DLL是一种包含可由多个程序同时使用的代码和数据的库。它允许程序在运行时加载和使用库中的函数和数据。
  2. 虚函数:虚函数是C++中实现多态的一种机制,允许派生类重写基类的函数。

步骤和示例代码

1. 创建动态链接库(DLL)

首先,创建一个包含虚函数的DLL项目。

DLL项目(MyLibrary)

代码语言:txt
复制
// MyLibrary.h
#pragma once

#ifdef MYLIBRARY_EXPORTS
#define MYLIBRARY_API __declspec(dllexport)
#else
#define MYLIBRARY_API __declspec(dllimport)
#endif

class MYLIBRARY_API Base {
public:
    virtual void VirtualFunction() = 0;
};

class Derived : public Base {
public:
    void VirtualFunction() override {
        // 实现虚函数
        std::cout << "Derived::VirtualFunction called!" << std::endl;
    }
};
代码语言:txt
复制
// MyLibrary.cpp
#include "MyLibrary.h"

编译生成DLL文件(MyLibrary.dll)和对应的导入库(MyLibrary.lib)。

2. 在可执行文件中使用DLL

接下来,在可执行文件中加载并使用DLL中的虚函数。

可执行文件项目(MyApp)

代码语言:txt
复制
// MyApp.cpp
#include <windows.h>
#include <iostream>
#include "MyLibrary.h"

typedef Base* (*CreateDerivedFunc)();

int main() {
    HMODULE hModule = LoadLibrary(L"MyLibrary.dll");
    if (!hModule) {
        std::cerr << "Failed to load DLL" << std::endl;
        return 1;
    }

    CreateDerivedFunc CreateDerived = (CreateDerivedFunc)GetProcAddress(hModule, "?CreateDerived@@YA?AVBase@@XZ");
    if (!CreateDerived) {
        std::cerr << "Failed to get function address" << std::endl;
        FreeLibrary(hModule);
        return 1;
    }

    Base* derived = CreateDerived();
    if (derived) {
        derived->VirtualFunction(); // 调用虚函数
        delete derived;
    }

    FreeLibrary(hModule);
    return 0;
}

3. 导出函数

为了在DLL中创建派生类实例,需要导出一个工厂函数。

MyLibrary.h

代码语言:txt
复制
extern "C" MYLIBRARY_API Base* CreateDerived();

MyLibrary.cpp

代码语言:txt
复制
#include "MyLibrary.h"

extern "C" MYLIBRARY_API Base* CreateDerived() {
    return new Derived();
}

相关优势

  1. 代码复用:DLL允许在多个应用程序之间共享代码,减少重复开发和维护成本。
  2. 模块化设计:通过将功能模块化,便于管理和更新。
  3. 动态加载:应用程序可以在运行时加载和卸载DLL,提高灵活性和启动速度。

应用场景

  1. 插件系统:允许第三方开发者为应用程序编写扩展功能。
  2. 大型项目:将复杂的应用程序分解为多个模块,便于开发和维护。
  3. 跨平台兼容性:通过DLL实现不同平台之间的代码共享。

常见问题及解决方法

  1. 找不到DLL文件:确保DLL文件在应用程序的执行路径中,或者设置正确的环境变量。
  2. 函数地址获取失败:检查函数名是否正确,确保DLL和可执行文件使用相同的编译器和配置。
  3. 内存泄漏:在使用完DLL对象后,及时释放内存。

通过以上步骤和示例代码,可以在C++项目中成功调用动态链接库中的虚函数。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

如何识别IDA反汇编中动态链接库中的函数

在使用IDA静态反汇编时,如果正在逆向的文件中有动态链接库函数(比如调用了程序自定义so库中的函数),IDA只会显示一个地址,跟进去会发现是延迟绑定中关于plt的代码,无法知道具体调用了哪个函数,对于逆向起来很是麻烦...按道理讲,虽然不能动态调试,静态分析不能看到运行时绑定的地址,但是具体动态链接的过程一定也是根据文件中的信息,所以静态也一定可以知道调用的是哪个函数,但是我没有发现如何使用IDA自动确定(如有高手麻烦留言告诉我...),于是通过查阅《程序员的自我修养》动态链接相关内容,找到了识别动态链接库中函数的方法。...ELF文件中还存储了needed的动态链接库,IDA中写在了该文件的最开始,向上拉窗口可以看到,我们只要从这些so库中找识别出的函数名即可。...使用 grep -rn “函数名” 即可找到调用的哪个库中的哪个函数。 ? 此外,还有这种形式的动态链接调用,再次挖坑做以记录碰到再研究。

3.2K70
  • C++中的虚函数与多态机制如何工作?

    在C++中,虚函数和多态机制是实现面向对象编程的重要概念。 虚函数是在基类中声明的函数,可以在派生类中进行重写。...当基类的指针或引用指向派生类的对象时,通过调用虚函数可以实现动态绑定,即在运行时确定要调用的函数。...在C++中,实现虚函数和多态机制需要两个关键点: 基类中声明虚函数:在基类中使用关键字virtual来声明一个函数为虚函数。...如果派生类中对虚函数进行了重写,那么就会调用派生类中的函数,实现了多态。...在main()函数中,创建了一个基类指针ptr指向派生类对象,通过该指针调用虚函数foo()时,会根据对象的实际类型调用派生类的函数,输出"Derived::foo()"。

    9210

    iOS客户端启动速度优化实践

    main()调用之前的加载过程 App开始启动后, 系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接库dyld,dyld是一个专门用来加载动态链接库的库。...执行从dyld开始,dyld从可执行文件的依赖开始, 递归加载所有的依赖动态链接库。...的存在,可执行文件和动态链接库在虚拟内存中的加载地址每次启动都不固定,所以需要这2步来修复镜像中的资源指针,来指向正确的地址。...我们可以优化的点有: 减少Objc类数量, 减少selector数量 减少C++虚函数数量 转而使用swift stuct(其实本质上就是为了减少符号的数量) Objc setup 这一步主要工作是:...+initialize中 尽量不要用C++虚函数(创建虚函数表有开销) main()调用之后的加载时间 在main()被调用之后,App的主要工作就是初始化必要的服务,显示首页内容等。

    1.9K10

    C++面试题

    静态链接和动态链接有什么区别? 静态链接,无论缺失的地址位于其它目标文件还是链接库,链接库都会逐个找到各目标文件中缺失的地址。...如此生成的可执行文件,仍缺失部分函数和变量的地址,待文件执行时,需连同所有的链接库文件一起载入内存,再由链接器完成剩余的地址修复工作,才能正常执行。 4....但是不论如何它依旧遵守多态的规则,也就是说,如果你的析构函数是虚函数,调用虚函数的规则也遵守多态原则,也就是会调用子类的析构函数,这和其他虚函数的机制完全一致,并没有什么不同。...gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段.rodata中。...动态分配的内存是在程序调用函数时才被分配,函数结束了,动态内存就应该被释放掉(别忘了手动释放)。 6. 如何构造一个类,使得只能在堆上或只能在栈上分配内存? 容易想到将构造函数设为私有。

    1.7K42

    硬核 | C++ 基础大全

    所以说,我们不应该在构在函数或析构函数中调用虚函数,就算调用一般也不会达到我们想要的结果。 析构函数的作用,如何起作用?...动态编译与静态编译 静态编译,编译器在编译可执行文件时,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库; 动态编译,可执行文件需要附带一个动态链接库...,在执行时,需要调用其对应动态链接库的命令。...缺点是哪怕是很简单的程序,只用到了链接库的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。...静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

    1.2K10

    一种Android App在Native层动态加载so库的方案

    这三个函数均在头文件中定义,它们的作用分别是:dlopen()打开一个动态链接库,返回一个动态链接库的句柄;dlsym()根据动态链接库句柄和符号名,返回动态链接库内的符号地址,这个地址既可以是变量指针...并把析构函数指针和so库句柄登记到一个以操作接口对象为键值的映射表中; 当需要释放关闭so库的时候,从映射表中取回析构函数指针和so库句柄,先调用析构函数释放操作接口对象,然后调用dlclose()函数...4. so库之间动态加载需要解决的问题 不同Native层模块的构建的STL版本不一致,会导致参数错误 由于动态加载的调用方和被调用方是分别构建成具体的so库或其他可执行文件,所以其中使用的来自C++...解决方法就是在调用方和被加载的so库都静态引用的公共数据定义中,定义一个虚基类作为操作接口。这个类的具体子类在被加载的so库中实现,调用方使用基类指针操作被加载的so库中的子类实例。...至于如何让调用方创建并获取被加载的so库里的子类实例,首先需要在被加载so库里的子类实现中定义两个前缀带有extern "C"的非成员函数,因为在C++中带有extern "C"这个前缀的函数,在符号名生成的处理将跟

    7.5K60

    CC++面试常问题集(1)

    根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种(动态链接库.so和静态链接库.a)   (1)静态链接   在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中...(2) 动态链接   在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。...在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。可移植性差。   ...对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。...),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是调用函数的局部变量。

    72040

    c比python快多少倍_python和c++哪个简单

    因此Python不适合用于底层算法的开发,应用在上层应用中作粘合剂或进行智能领域的研究比较占优;C/C++则适合用于底层控制算法编程。...下面主要介绍Python调用C++,让C++和Python形成优势互补。...2 Python调用C++的主要方式 主要介绍三种C++/Python联合编程的方式: 2.1 SWIG 支持Python、Java、Ruby等语言调用C接口 文档全面,易于学习 绑定性能欠佳, 不支持属性和内部类封装...建议在根目录下新建bin目录管理生成的库文件 # VS2019编译的x86库文件 bin/lib32-msvc-14.2 # VS2019编译的x64库文件 bin/lib64-msvc-14.2...toolset:表示编译器,可选gcc、msvc-14.2(VS2019)等 link:指定生成动态链接库shared还是静态链接库static,推荐使用静态库方式编译,这样发布程序时无需连带发布Boost

    1.9K30

    CMake构建学习笔记11-minizip库的构建

    另一个问题是,minizip其实是个可执行程序,Windows下不能直接将其构建成动态链接库,因为Windows下的动态链接库是需要设置导出的,否则就会提示找不到符号的问题。...但是在Windows下笔者还是倾向于优先使用动态库。一直以来,二进制兼容的问题一直是困扰C/C++编程的重要问题。...以后的版本就会开始提供二进制兼容的特性了,原理是标准库、运行时库(如 msvcp140.dll)、C++ 标准库保证了ABI(二进制接口)的稳定。...笔者也确实发现很多产品的MSVC的预编译成果能够在MSVC环境中混用了。比如VS2017编译的Qt就能够在VS2019的环境下正常使用。...不过这些能混用的成果一般都是动态库,也就是动态库的二进制兼容特性更好一点。至于静态库,文档中宣称静态库也可以做到,但是笔者实测至少这个基于VS2017的minizip静态库在VS2019中用不了。

    8100

    适合具备 C 语言基础的 C++ 教程(九)

    前言 在上一则教程中,叙述了关于C++类型转换的相关内容,在本节教程中,将叙述 C++的另一个内容,也就是抽象,这也是 C++相对于 C语言来说独特的一点,下面我们就来着重叙述这一点。...抽象类 上述引出了纯虚函数的写法,那纯虚函数和抽象类之间有什么关系呢?实际上,抽象类就是具有纯虚函数的类,那这抽象类存在的意义是什么呢?.../Human,与前面的教程不同,这次在运行可执行文件的时候,多了LD_LIBRARY_PATH=./,这是因为现在使用了动态库,而这条多出来的语句是来指明动态库的路径的。...<<"use chopsticks to eat,test"<<endl; } 然后,如果没有使用动态链接库,那么这个时候,如果要执行这个修改过的代码,就需要重新生成可执行文件,但是现在使用了动态链接库...,也就是说,不需要重新生成可执行文件了,我们只需要重新生成动态链接库就好了,编译命令如下所示: ?

    40420

    适合具备 C 语言基础的 C++ 入门教程(九)

    前言 在上一则教程中,叙述了关于C++类型转换的相关内容,在本节教程中,将叙述 C++的另一个内容,也就是抽象,这也是 C++相对于 C语言来说独特的一点,下面我们就来着重叙述这一点。...抽象类 上述引出了纯虚函数的写法,那纯虚函数和抽象类之间有什么关系呢?实际上,抽象类就是具有纯虚函数的类,那这抽象类存在的意义是什么呢?.../Human,与前面的教程不同,这次在运行可执行文件的时候,多了LD_LIBRARY_PATH=./,这是因为现在使用了动态库,而这条多出来的语句是来指明动态库的路径的。..."use chopsticks to eat,test"<<endl; } 然后,如果没有使用动态链接库,那么这个时候,如果要执行这个修改过的代码,就需要重新生成可执行文件,但是现在使用了动态链接库,...也就是说,不需要重新生成可执行文件了,我们只需要重新生成动态链接库就好了,编译命令如下所示: [image-20210223191802201] 可见,上述只重新生成了Human库文件,并没有重新生成可执行文件

    42210

    C++调用C语言写成的动态链接库

    1.C++和C生成的符号信息不一样 C++在语法上是兼容C的,但是这不代表使用C语言不做任何处理直接写成的动态链接库就可以被C++给调用。...这就导致C语言和C++语言生成的函数签名是不同的,故不能不做任何处理直接调用。下面我们来看一下C和C++编译同样一段代码为动态链接库以后的,它们的函数符号信息有什么不一样。...下面编译它们为动态链接库。 ? 下面使用nm命令来查看生成的函数符号信息。 ? 可以看到gcc和g++生成的函数符号信息是不同的,因此,不做任何处理肯定是不能直接调用的。...这里使用nm命令可以查看符号信息是因为我们没有给这两个动态链接库进行“瘦身”。在实际开发和应用中,你的动态链接库应该先进行“瘦身”。命令如下: ?...2.如何使C++能调用C动态链接库 C语言提供了extern "C"来使得C++能够调用C。

    3K20

    《逆袭进大厂》第三弹之C++提高篇79问79答

    3、抽象类  包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。 111、 继承机制中对象之间如何转换?指针和引用之间如何转换?...在C/C++中,对函数参数的扫描是从后向前的。...在使用静态库的情况下,在编译链接可执行文件时,链接器从库 中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。...,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库; 2) 动态编译的可执行文件需要附带一个动态链接库,在执行时,需要调用其对应动态链接库的命令...缺点是哪怕是很简单的程序,只用到了链接库的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。

    2.2K30

    浅析C++内存布局

    C++程序在内存中的布局是怎样的?总结下C++内存布局的相关知识。 概述 简单总结下C++变量在内存中的布局和可执行文件相关的知识。暂未涉及虚函数,虚函数表,类的继承和多态等C++对象的内存模型。...包括:代码指令是如何保存的,库文件如何与应用程序代码静态链接,应用程序如何被装载到内存中并开始运行,动态链接如何实现,C/C++运行库的工作原理,以及操作系统提供的系统服务是如何被调用的。...添加虚函数之后,类的变化 当类中添加了虚函数时,类的大小变为4,同时编译器给类中添加了虚函数表指针vfptr 这个指针指向了vftable,vftable 这张表里面存放的本类所有的虚函数入口地址。...2.当发生继承时,子类会将父类的虚函数表指针继承下来,指向父类的的虚函数表,在子类调用构造函数后,编译器会将该指针指向自己的虚函数表。...4.程序运行时,通过父类指针或者引用 调用函数时,编译器会先找到该对象中的虚函数指针,根据指针找到虚函数表,在虚函数表中找到对应的函数入口 地址进行调用。

    1.2K40

    低级工具——C语言C++

    例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。...根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种: (1)静态链接:在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。...(2)动态链接:在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。...在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。...对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。

    2.1K10

    Python遇见C++碰出的编译火花

    例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。...根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种: 静态链接:在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。...动态链接:在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。...在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。...对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。

    99510

    【操作系统】动态链接库

    动态链接库 DLL就是整个windows操作系统的基础。动态链接库不能直接运行,也不能接收消息。他们就是一些独立的文件。 Windows API中的所有函数都包含在DLL中。...在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件)。...在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,而是在运行时候,再去加载DLL,访问DLL中导出的函数。..._stdcall标准的调用约定 C/C++ MFC Delphi 用pacal 是从左至右的压栈方式。...如果我们在动态链接库中使用标准调用约定_stdcall,而在可执行程序中使用动态加载DLL,会发生名字重编,如果知道DLL中函数的序号,这时可以使用宏MAKEINTRESOURCE把序号转变成名字。

    81720

    分享一份实战linux面试题目!

    为什么不可以 20、可不可以更改虚函数表的内容 21、你了解过CVTE吗 22、串行通信的协议有哪些 23、对加班的看法 24、编程:输出一个字符串中连续出现次数最多的字符,输出的是最后一个 1、从文件到可执行文件的过程...2、struct结构体与class 3、c语言中struct实现类,怎么实现结构体中有函数 4、进程空间模型 5、一个linux API怎么调用的底层 6、设计模式 7、C++中类的成员函数与类的静态成员函数存储在代码段还是数据段还是哪里...8、C++中类的成员变量与类的静态成员变量存储在代码段还是数据段还是哪里?...9、C++初始化列表与在括号中初始化有什么区别 10、什么情况下必须在初始化列表中进行初始化 11、多态的基本原理 12、为什么析构函数要为虚函数(请深层次剖析,说底层的原因) 13、多个线程之间有什么是共享的...39、怎么制作动态链接库,说说动态链接与静态链接是什么 40、说一说gcc的-l选项和-L选项是干什么的 41、请你解释解释面向对象与面向过程的区别 三、总结: 温馨提示,面试过程中不要太紧张,正常回答技术问题就行

    58830
    领券