尝试使用dll中的函数时出错

时间:2011-06-19 01:43:55

标签: c++ vc6

我的代码:

DLL:

#include "stdafx.h"
#include <iostream.h>

extern "C" __declspec(dllexport) void F1()
{
    cout << "It works\n";
}

extern "C" __declspec(dllexport) int F2()
{
    return 154827;
}

extern "C" __declspec(dllexport) void F3(int n)
{
    cout << "It works: "<<n<<"\n";
}

extern "C" __declspec(dllexport) int F4(int n)
{
    return n+1;
}

控制台应用程序:

#include "stdafx.h"
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#include <conio.h>

typedef void (WINAPI*f1)();
typedef int (WINAPI*f2)();
typedef void (WINAPI*f3)(int);
typedef int (WINAPI*f4)(int);

#define MAXMODULE 50

f1 F1;
f2 F2;
f3 F3;
f4 F4;

void main(int argc, char* argv[])
{
    HINSTANCE hLib=LoadLibrary("dllll.dll");

    if(hLib==NULL)
    {
        cout << "Unable to load library!" << endl;
        getch();
        return;
   }

    char mod[MAXMODULE];

   GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
   cout << "Library loaded: " << endl;


    F1=(f1)GetProcAddress((HMODULE)hLib, "F1");
    F2=(f2)GetProcAddress((HMODULE)hLib, "F2");
    F3=(f3)GetProcAddress((HMODULE)hLib, "F3");
    F4=(f4)GetProcAddress((HMODULE)hLib, "F4");

   if((F1==NULL) || (F2==NULL) || (F3==NULL) || (F4==NULL)) {

        cout << "Unable to load function(s)." << endl;
        FreeLibrary((HMODULE)hLib);
        return;
   }

   F1();
   cout<<F2()<<endl;
   F3(1515);
   cout << F4(12) << endl;   //works now :)

   FreeLibrary((HMODULE)hLib);

   getch();

    return;
}

输出:

Library loaded:
154827
It works
It works: 1515

问题:
1.为什么在F2之后显示F1?在F2之前调用F1 2. F3正常工作,但会弹出两次窗口。我点击忽略它。
http://s3.ifotos.pl/img/f3_hwpwapq.jpg
3.为什么F4根本不起作用?它提出了一个例外。

编辑:
问题2和3现在已经解决了。

对于1,现在输出为:

Library loaded:  
154827  
13  
It works  
It works: 1515  

按顺序:F2,F4,F1,F3。
我称之为:F1,F2,F3,F4 为什么会这样?

2 个答案:

答案 0 :(得分:2)

看起来你有错误的调用约定。尝试将WINAPI__stdcall)更改为__cdecl

typedef void (__cdecl *f1)();
typedef int (__cdecl *f2)();
typedef void (__cdecl *f3)(int);
typedef int (__cdecl *f4)(int);

答案 1 :(得分:2)

可能发生的事情是您的DLL和可执行文件链接到不同版本的C ++运行时库。由于现在有两个不同版本的C ++运行时库存在于进程的地址空间中,因此有两个独立的内存缓冲区用于stdout。由于您没有刷新DLL函数中的数据,但是 在可执行文件中刷新它(请注意,打印新行'\n'不会刷新,而是打印{{1 flush),这就是:

  1. 调用F1,std::endl被写入DLL的libc ++ stdout内存缓冲区。
  2. 调用F2,并将"It works\n"写入可执行文件的libc ++ stdout内存缓冲区。对154827\n的调用会刷新缓冲区并将其打印到控制台。
  3. 调用F3,并将std::endl写入DLL的libc ++ stdout内存缓冲区。
  4. 调用F4,并将"It works: 1515\n"写入可执行文件的libc ++ stdout内存缓冲区。对13的调用会刷新缓冲区并将其打印到控制台。
  5. 您的进程退出,导致您的DLL被卸载。作为清理例程的一部分,libc ++刷新其输出缓冲区,导致std::endl打印到控制台。
  6. 此修复程序是为了确保您在DLL和可执行文件中使用相同的C ++(和C)运行时库。有关详细信息,请参阅this page - 我建议对可执行文件和DLL使用多线程版本DLL版本("It works\nIt works: 1515\n"编译器选项)。

    另见Potential Errors Passing CRT Objects Across DLL Boundaries