动态调用DLL技术很常见也没有什么特别困难的,但是我总是感觉写起来很烦,要用typedef定义,加载DLL、查找地址,很烦人,所以我找了一个方式,把DLL动态调用的逻辑都封装成了一个类,使用起来就简单多了。
直接动态调用的方法,示例如下:
1、预定义
typedef LinphoneCore* (*funlinphone_core_new)(const LinphoneCoreVTable *vtable,const char *config_path, const char *factory_config, void* userdata);
2、定义函数指针变量 funlinphone_core_new pfn_core_new ;
3、动态加载函数 handle = LoadLibrary( "liblinphone-4.dll"); pfn_core_new = (funlinphone_core_new)GetProcAddress( handle,"linphone_core_new");
4、调用
pfn_core_new(....);
|
这样调用就完成了,还得负责清理(函数指针指向NULL,卸载DLL等工作)。
使用类封装,先要使用下面一个类(添加到工程即可)
/**************************************************************************** * DEFINE_PROC * Inputs: * result: The result type; if a linkage type such as WINAPI, CALLBACK, * etc. is required, use DEFINE_PROC_LINKAGE * name: The function name * args: The argument list, enclosed in parentheses * Notes: * There are as many of these as required for your methods to be called ****************************************************************************/ #define DEFINE_PROC(result, name, args) \ protected: \ typedef result (*name##_PROC) args; \ public: \ name##_PROC name; /**************************************************************************** * DEFINE_PROC_LINKAGE * Inputs: * result: Result type * linkage: Linkage type, e.g., CALLBACK, WINAPI * name: Function name * args: Argument list enclosed in ( )s * Notes: * There are as many of these as required for your methods to be called ****************************************************************************/ #define DEFINE_PROC_LINKAGE(result, linkage, name, args) \ protected: \ typedef result (linkage * name##_PROC) args; \ public: \ name##_PROC name; /**************************************************************************** * IMPLEMENT_PROC * Inputs: * name: The name of the function, as used as the second argument of * DEFINE_PROC. * Notes: * This must appear between a BEGIN_PROC_TABLE and END_PROC_TABLE ****************************************************************************/ #define IMPLEMENT_PROC(name) \ IMPLEMENT_PROC_SPECIAL(name, #name) /**************************************************************************** * IMPLEMENT_PROC_SPECIAL * Inputs: * name: The name as defined by IMPLEMENT_PROC or IMPLEMENT_PROC_LINKAGE * externalname: The external name * Notes: * This must appear between a BEGIN_PROC_TABLE and END_PROC_TABLE ****************************************************************************/ #define IMPLEMENT_PROC_SPECIAL(name, externalname) \ name = loading ? (name##_PROC)GetProcAddress(library, externalname) : NULL; \ { \ DWORD err = ::GetLastError(); \ if(loading) \ ASSERT(name != NULL); \ if(loading && name == NULL) \ { \ ::SetLastError(err); \ } \ } /**************************************************************************** * BEGIN_PROC_TABLE * END_PROC_TABLE * Effect: * This declares the method that initializes the method pointers. * There can be only one BEGIN_PROC_TABLE declaration per class. * Following this are some number of IMPLEMENT_PROC lines, * followed by END_PROC_TABLE ****************************************************************************/ #define BEGIN_PROC_TABLE() protected: virtual BOOL Define(BOOL loading) { ::SetLastError(ERROR_SUCCESS); #define END_PROC_TABLE() return TRUE; } /**************************************************************************** * DECLARE_PROC_DLL * Inputs: * myclass: The name of your subclass. This must be the same as * the class name you used to declare the class * superclass: This allows you to derive additional subclasses; * normally you will use the DynamicDLL class here * Effect: * Defines the constructors and destructors for the subclass ****************************************************************************/ #define DECLARE_PROC_DLL(myclass, superclass) \ public: \ myclass() : superclass() {} \ myclass(LPCTSTR module) : superclass(module) { Load(module); } \ virtual ~myclass() { Free(); } /**************************************************************************** * DynamicDLL * This is the abstract superclass on which all other classes are based * It defines the basic behavior of the class. ****************************************************************************/ class DynamicDLL { public: DynamicDLL() { Init(); } DynamicDLL(LPCTSTR name) { Init(); } virtual ~DynamicDLL() { } BOOL Load(LPCTSTR name) { ::SetLastError(ERROR_SUCCESS); ASSERT(library == NULL); // Attempt to load twice? if(library != NULL) { /* already loaded */ //::SetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* already loaded */ library = ::LoadLibrary(name); if(library != NULL) return Define(TRUE); Free(); return FALSE; } void Free() {if(library != NULL) ::FreeLibrary(library); library = NULL; Define(FALSE); } BOOL IsLoaded() { return library != NULL; } protected: void Init( ) { library = NULL; } HINSTANCE library; virtual BOOL Define(BOOL loading) { ASSERT(FALSE); return FALSE; } // must define in subclass // Did you forget to do a BEGIN_PROC_TABLE? }; /**************************************************************************** * Example ****************************************************************************/ //class TestDynDLL: public DynamicDLL { // DECLARE_PROC_DLL(TestDynDLL, DynamicDLL) // // DEFINE_PROC(LRESULT, Test, (LPCTSTR, int)) // DEFINE_PROC_LINKAGE(BOOL, WINAPI, Test2, ( ) ) // // BEGIN_PROC_TABLE() // IMPLEMENT_PROC(Test) // IMPLEMENT_PROC_SPECIAL(Test2, "_Test2@0") // END_PROC_TABLE() // //}; |
有了这个类,就可以作为封装DLL调用的基础。
示例如下,例如调用windows中,user32.dll中的函数MessageBoxA,步骤如下:
首先,建立一个新的类,继承DynamicDLL类,在其中,声明所需使用的函数:
#include "DynamicDLL.h" class TestDynDLL: public DynamicDLL { DECLARE_PROC_DLL(TestDynDLL, DynamicDLL) DEFINE_PROC_LINKAGE(int, WINAPI, MessageBoxA, ( HWND,LPCSTR,LPCSTR,UINT) ) BEGIN_PROC_TABLE() IMPLEMENT_PROC(MessageBoxA) END_PROC_TABLE() }; |
在需要调用的地方,调用上面这个类:
TestDynDLL * DLL; DLL = new TestDynDLL(_T("user32.dll")); ASSERT(DLL->IsLoaded()); int rr = DLL->MessageBoxA(this->GetSafeHwnd(),(LPCSTR)"22",(LPCSTR)"dsasdsa",MB_OK); delete DLL; |
怎么样,是不是感觉好用多了?我没有在Linux下面测,估计稍加改动,Linux也能使用这种机制。
需要注意的是,在继承类中的这个声明,需要仔细写,函数名、参数、返回值、调用约定都需要保持一致,否则会出错的哦。
相关推荐
本文将深入探讨如何使用C++调用WebService并封装成动态链接库(DLL),以便其他应用程序能够轻松地调用这些功能。 首先,我们需要理解WebService的基本概念。WebService是一种基于标准的、平台和语言无关的接口,它...
例如,可以封装一个`Socket`类,包含初始化、连接、发送和接收数据的方法。 - 为了导出这些函数到DLL,需要使用`__declspec(dllexport)`关键字来声明函数。在DLL的头文件中,将这些函数声明为`dllexport`,而在使用...
动态链接库(Dynamic Link Library, DLL)是Windows操作系统中的一个概念,而共享对象库(Shared Object, SO)则是Linux系统下的等价物。本篇将详细介绍C语言在Windows和Linux系统下如何实现动态链接库的封装以及如何...
提供java jni示例程序,linux so工程,windows dll工程,将科大讯飞语音合成程序封装成windows支持的dll和linux支持的so并且导出api,java使用jni直接调用。代码均已编译测试通过,需要appid和mscdll则可以自己去...
一个常见的场景是C#调用C++编写的动态链接库(DLL)。然而,在这种情况下可能会遇到一些问题,比如当向C++ DLL传递字符串参数时程序崩溃的情况。本文将详细探讨这一问题,并提供一种可能的解决方案。 #### 问题背景...
为了解决上述问题,一种常见的策略是请求C++团队编写一个DLL文件来负责解析二进制数据,然后Java应用通过调用该DLL来获取解析后的结果,通常是以JSON格式返回。这就涉及到如何在Java中调用DLL的问题。 #### 方案...
5. **创建C#接口**:在C#项目中,创建一个类来封装DLL的调用,定义DllImport属性以指定DLL中的函数。这些函数可能包括初始化模型、进行推理和释放资源等。 6. **调用DLL**:在C#代码中,实例化上述类,然后调用其...
为了编译生成.so文件,我们需要一个Makefile来指导NDK如何处理源代码。以下是一个简单的Makefile示例: ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := add LOCAL_SRC_FILES :...
在Java程序中调用DLL(动态链接库)文件通常是通过JNI(Java Native Interface)来实现的,而JNative是JNI的一个封装库,它提供了一种更简洁的方式来调用C/C++编写的本地代码。这篇博客文章可能介绍了如何利用...
在Delphi中,我们可以使用`library`关键字来定义一个共享库。在library块内,声明公共函数和类型,这些将在其他应用程序中使用。例如: ```delphi library MyLib; uses System.SysUtils; exports MyFunction ...
DLL(Dynamic Link Library)是Windows操作系统中的一个核心组件,它封装了一系列可重用的功能,允许不同程序共享代码和资源,提高效率。当我们谈论"CVI调用DLL"时,我们关注的是如何在CVI环境中使用DLL文件来扩展或...
创建一个Java接口,声明你打算调用的DLL函数。接口中的方法必须使用`native`关键字,并且不提供实现。例如,如果你有一个名为`MyDllFunction`的函数,其原型为`int MyDllFunction(int param)`,则接口定义如下: `...
在本文中,我们将深入探讨如何使用Qt框架封装一个带界面的纯虚类动态库。Qt是一个流行的开源跨平台应用程序开发框架,广泛应用于GUI(图形用户界面)开发。它提供了丰富的类库,支持C++编程,并且可以运行在多种操作...
标题“java调用c++生成so库”指的是在Linux环境下,通过JNI技术,Java程序可以调用预先用C++编译生成的动态链接库(.so文件)。.so文件是Linux下的动态共享对象,相当于Windows下的.DLL文件,它包含了可由多个程序...
4. **编译C++代码**:将C++源代码编译为动态链接库(在Windows上是.dll,在Linux上是.so,在macOS上是.dylib)。确保正确链接了JNI库。 5. **加载库**:在Java中,`System.loadLibrary()`会加载前面创建的动态链接...
在Windows系统中,动态调用库函数通常涉及到DLL(Dynamic Link Library)文件,而在Unix/Linux环境中,我们则使用共享对象库(.so文件)。动态调用库函数的一个主要优点是能够减少内存占用,因为多个程序可以共享...
在IT行业中,为了方便开发和集成,经常会将Redis的操作接口封装成一个动态库,便于其他应用程序调用。本篇文章将深入探讨Redis封装动态库的相关知识点。 一、Redis动态库的构建 1. 封装接口:首先,我们需要识别...
在 Java 程序中,我们可以使用 native 定义一个方法来调用这个 dll 文件: public native int readData(int icdev, int offset, int len, byte[] dataBuffer ); 然后,我们可以使用 JNI 来加载这个 dll 文件,并在...
资料; 非常感谢,如有侵权,请与本人联系;...本demo的BaiduFaceDll\BaiduFaceDll目录,是本封装dll的c++源码。VS版本为2015,Framework版本为4.0。 本DEMO只是封装了几个示例,其余封装,参考样式自行编写;
标题中的“jnative调用动态库”指的是Java中使用JNative库来调用本地(操作系统级别的)动态链接库(DLL或SO文件)的技术。在Java中,为了与操作系统底层功能进行交互,比如调用C/C++编译的库,我们可以使用Java ...