SetDllDirectory LoadLibrary在DLL中 [英] SetDllDirectory LoadLibrary inside a DLL

查看:410
本文介绍了SetDllDirectory LoadLibrary在DLL中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以在C ++ DLL中使用C ++ SetDllDirectory LoadLibrary 命令来加载另一个DLL吗?我已经尝试使用它们像这样:



可执行程序调用第一个DLL,
然后第一个DLL加载第二个DLL,
然后第二个DLL计算...



但是当我运行可执行文件时,我收到此错误消息:


此应用程序请求运行时以异常方式终止它。有关详细信息,请联系应用程序支持团队。


第二个DLL直接链接到可执行文件时工作正常!



我的可执行文件中的代码:

  #include< windows.h> 
#include< iostream>

int main(){
HINSTANCE hDLL_Link = NULL;
SetDllDirectory((LPCWSTR)LC:\\Users\\MC\\Documents\\2014_07_01a_FDD_VC2008\\test_call_DLL\\EXE_calls_Link_DLL\\Release) ;
hDLL_Link = LoadLibrary((LPCWSTR)LLink_DLL.dll);
if(hDLL_Link == NULL)std :: cout<<did not load<<'\\\
';
typedef void(* Ptr_OPS_Link)();
Ptr_OPS_Link Ptr_OPS_Link_0;
Ptr_OPS_Link_0 =(Ptr_OPS_Link)GetProcAddress(hDLL_Link,OPS_Link);
Ptr_OPS_Link_0();
FreeLibrary(hDLL_Link);
system(pause);
}

这是第一个DLL中的代码:

  #includeLink.h

externC__declspec(dllexport)
void OPS_Link b $ b Link * Link_Ptr_Object = NULL;
if(Link_Ptr_Object == NULL){
Link_Ptr_Object = new Link();
}
if(Link_Ptr_Object == NULL){
//不能在标记为externC的__declspec(dllexport)函数中抛出,这就是std :: cout实现的原因:
std :: cout<<错误:无法链接到FDD DLL<''\ n';
system(pause);
}
delete Link_Ptr_Object;
Link_Ptr_Object = NULL;
}

Link :: Link()
:m_void_Ptr_ObjectByDLL(NULL){
HINSTANCE hDLL = NULL; //处理DLL
SetDllDirectory LPCWSTR)LC:\\Software\\Octave-3.6.1 \\bin\\);
hDLL = LoadLibrary((LPCWSTR)LC:\\Users\\MC\\Documents\\2014_07_01a_FDD_VC2008\\Executable\\Release\\FDD_DLL .dll);
if(hDLL == NULL){
throw无法加载DLL;
} else if(hDLL!= NULL){
typedef void(* Ptr_OPS_FDD)(std :: string,int,int);
Ptr_OPS_FDD Ptr_OPS_FDD_0; //指向过程的指针DLL
Ptr_OPS_FDD_0 = NULL;
Ptr_OPS_FDD_0 =(Ptr_OPS_FDD)GetProcAddress(hDLL,OPS_FDD);
if(Ptr_OPS_FDD_0 == NULL){
FreeLibrary(hDLL);
throwDLL导出函数地址无法确定;
} else {
//运行DLL中的过程:
Ptr_OPS_FDD_0(FDD_INPUT_Truss_Bridge_Data2_Ambient_Inch_11Channels_77824Samples_SamplingFreq_256Hz.txt,11,256); // LabScaleTruss
//Ptr_OPS_FDD_0(\"FDD_INPUT_Ambient_EW_15Channels_3000Samples_SamplingFreq_20Hz.txt ,15,20); // AmbientEW
//Ptr_OPS_FDD_0(\"FDD_INPUT_Meriden_3Channels(3_5_8)_3686400Samples_SamplingFreq_2048Hz.txt\",3,2048);//eridenBridge
FreeLibrary(hDLL);
}
}
}


解决方案>

您的代码中有一些可能会导致失败的情况:


  1. 如果无法加载DLL,

  2. 您传递的内部使用动态分配的对象,因此将使用堆管理器。

对于上面的 1。,如果无法找到库,您的main()函数只执行一个简单的 cout 然而,不是退出, main 函数就好像找到库一样。



对于上面的 2。,传递 std :: string 作为DLL函数的参数是容易出错,不推荐,除非你知道你正在做什么。容易出错的原因是




  • 包含函数调用的DLL可能使用不同的选项集合调用该函数的DLL。这些不同的选项可能会影响 std :: string 的实现方式,以及内存中的布局等。


  • 包含函数调用的DLL可能由与调用函数的DLL不同的编译器版本构建。同样的问题,不同的实现 std :: string


  • DLL和模块使用std: :string可能未使用C运行时库的 DLL版本构建。如果DLL的/ modules不是使用DLL版本的运行时库来构建和链接的,那么DLL将使用与模块不同的堆。由于使用不同的内存堆,对std :: string的任何操作都将无效。




,除非您可以保证


  1. 您正在使用完全相同版本的编译器构建模块和DLL


  2. $ b
    p>然后传递 std :: string 作为参数,一般来说,传递任何维护动态分配的内存的对象可能会或可能导致运行时错误。


    Can I use C++ SetDllDirectory and LoadLibrary commands inside a C++ DLL to load another DLL? I have tried using them like this:

    Executable calls the 1st DLL, then 1st DLL loads the 2nd DLL, then 2nd DLL does the calculations...

    but when I run the executable, I get this error message:

    This application has requested the Runtime to terminate it in an unusual way. Please contact the applications support team for more information.

    2nd DLL works fine when linked directly to Executable!

    This is the code inside my executable:

    #include <windows.h>
    #include <iostream>
    
    int main(){
        HINSTANCE hDLL_Link=NULL;
        SetDllDirectory((LPCWSTR)L"C:\\Users\\MC\\Documents\\2014_07_01a_FDD_VC2008\\test_call_DLL\\EXE_calls_Link_DLL\\Release");
        hDLL_Link=LoadLibrary((LPCWSTR)L"Link_DLL.dll");
        if(hDLL_Link==NULL) std::cout<<"did not load"<<'\n';
        typedef void (*Ptr_OPS_Link)();
        Ptr_OPS_Link Ptr_OPS_Link_0;
        Ptr_OPS_Link_0=(Ptr_OPS_Link)GetProcAddress(hDLL_Link,"OPS_Link");
        Ptr_OPS_Link_0();
        FreeLibrary(hDLL_Link);
        system("pause");
    }
    

    this is the code inside the 1st DLL:

    #include "Link.h"
    
    extern "C" __declspec(dllexport)
    void OPS_Link(){
        Link*Link_Ptr_Object=NULL;
        if(Link_Ptr_Object==NULL){
            Link_Ptr_Object=new Link();
        }
        if(Link_Ptr_Object==NULL){
            //can not throw inside __declspec(dllexport) functions marked extern "C" that's why std::cout is implemented:
            std::cout<<"Error: could not link to FDD DLL"<<'\n';
            system("pause");
        }
        delete Link_Ptr_Object;
        Link_Ptr_Object=NULL;
    }
    
    Link::Link()
    :m_void_Ptr_ObjectByDLL(NULL){
        HINSTANCE hDLL=NULL;//handle to DLL
        SetDllDirectory((LPCWSTR)L"C:\\Software\\Octave-3.6.1\\bin\\");
        hDLL=LoadLibrary((LPCWSTR)L"C:\\Users\\MC\\Documents\\2014_07_01a_FDD_VC2008\\Executable\\Release\\FDD_DLL.dll");
        if(hDLL==NULL){
            throw "DLL loading could not be done";
        }else if(hDLL!=NULL){
            typedef void (*Ptr_OPS_FDD)(std::string, int, int);
            Ptr_OPS_FDD Ptr_OPS_FDD_0;//pointer to procedure inside DLL
            Ptr_OPS_FDD_0=NULL;
            Ptr_OPS_FDD_0=(Ptr_OPS_FDD)GetProcAddress(hDLL,"OPS_FDD");
            if(Ptr_OPS_FDD_0==NULL){
                FreeLibrary(hDLL);
                throw "DLL exported function address could not be determined";
            }else{
                //run the procedure inside DLL:
                Ptr_OPS_FDD_0("FDD_INPUT_Truss_Bridge_Data2_Ambient_Inch_11Channels_77824Samples_SamplingFreq_256Hz.txt",11,256);//LabScaleTruss
                //Ptr_OPS_FDD_0("FDD_INPUT_Ambient_EW_15Channels_3000Samples_SamplingFreq_20Hz.txt",15,20);//AmbientEW
                //Ptr_OPS_FDD_0("FDD_INPUT_Meriden_3Channels(3_5_8)_3686400Samples_SamplingFreq_2048Hz.txt",3,2048);//MeridenBridge
                FreeLibrary(hDLL);
            }
        }
    }
    

    解决方案

    There are a few things in your code that can cause failure:

    1. You do not exit if the DLL cannot be loaded:
    2. You are passing objects that internally use dynamic allocation, and thus will use the heap manager.

    For 1. above, your main() function only does a simple cout if the library cannot be found. However instead of exiting, the main function proceeds as if the library was found.

    For 2. above, passing std::string as a parameter to a DLL function is error prone and not recommended unless you know exactly what you're doing. The reason it is error prone is

    • The DLL that contains the function call may have been built with a different set of options than the DLL that calls the function. These differing options could cause a difference in the way that std::string is implemeted, how it's layed out in memory, etc.

    • The DLL that contains the function call may have been built by a different version of the compiler than the DLL that calls the function. Again, same issue with differing implementations of std::string

    • The DLL's and modules using std::string may not have been built using the DLL version of the C runtime library. If the DLL's/modules are not built and linked using the DLL version of the runtime library, the DLL will be using a different heap than the module. Any operation on std::string will be invalid, due to differing memory heaps being used.

    So in a nutshell, unless you can guarantee that

    1. You are building the modules and DLL's with the exact same version of the compiler and compiler options.
    2. You are linking all modules to the DLL version of the runtime library.

    Then passing std::string as a parameter, and in general, passing any object that maintains dynamically allocated memory, may or will lead to runtime errors.

    这篇关于SetDllDirectory LoadLibrary在DLL中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆