Visual C ++如何为Delphi导出x64 DLL函数

时间:2012-06-23 11:08:51

标签: c++ visual-studio dll 64-bit

我主要是Delphi开发人员,我一直在使用DLL包装器,它与Logitech的G15等api DLL接口,与键盘LCD屏幕进行交互。

几年前,有些人将这个包装器与delphi一起使用,基本上是一个DLL与Logitech lib连接并将函数导出到Delphi。它一直工作正常,但它只有32位。

我得到了包装器源并尝试将其编译为64位,但出了点问题。我将平台设置为64位,相应地更改了配置等(我认为),并将库路径指向Logitech 64位.lib

导出似乎存在,但是当我尝试使用GetProcAddress加载任何内容时,我收到错误“无法找到指定的模块”

怎么了?

enter image description here

// lgLCDWrapper.DLL
//
// A Wrapper-DLL for Delphi and other compilers who cannot include the original
// lcLcd.Lib provided by Logitech. These functions are needed to communicate with
// the graphical LCD of an Logitech G15-Keyboard.
//
// Code by Olaf Stieleke, May 1st, 2007
// Compiler Visual C++ 2005 Express Edition
// Hereby dedicated to Open Source under GPL-License.
//

//Make sure to set additional Include-Path to lglcd.h (found in Logitech-SDK-Folders)
//Make sure to set additional Library-Path to lglcd.lib (found in Logitech-SDK-Folders)

#include "stdafx.h"
#include <lglcd.h>
#include "lgLcdWrapper.h"


BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,LPVOID lpReserved)
{
    return TRUE;
}

DWORD _cdecl lgLcdInitWrap(void)
{
    return lgLcdInit();
}

DWORD _cdecl lgLcdDeInitWrap(void)
{
    return lgLcdDeInit();
}
DWORD _cdecl lgLcdConnectAWrap(lgLcdConnectContextA *ctx)
{
    return lgLcdConnectA(ctx);
}
DWORD _cdecl lgLcdDisconnectWrap(int connection)
{
    return lgLcdDisconnect(connection);
}
DWORD _cdecl lgLcdEnumerateWrap(int connection, int index, lgLcdDeviceDesc *description)
{
    return lgLcdEnumerate(connection,index,description);
}
DWORD _cdecl lgLcdOpenWrap(lgLcdOpenContext *ctx)
{
    return lgLcdOpen(ctx);
}
DWORD _cdecl lgLcdCloseWrap(int device)
{
    return lgLcdClose(device);
}
DWORD _cdecl lgLcdReadSoftButtonsWrap(int device, DWORD *buttons)
{
    return lgLcdReadSoftButtons(device,buttons);
}
DWORD _cdecl lgLcdUpdateBitmapWrap(int device, lgLcdBitmapHeader *bitmap, DWORD priority)
{
    return lgLcdUpdateBitmap(device,bitmap,priority);
}
DWORD _cdecl lgLcdSetAsLCDForegroundAppWrap(int device, int foregroundYesNoFlag)
{
    return lgLcdSetAsLCDForegroundApp(device,foregroundYesNoFlag);
}

包含文件

extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdInitWrap(void);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdDeInitWrap(void);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdConnectAWrap(lgLcdConnectContextA *ctx);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdDisconnectWrap(int connection);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdEnumerateWrap(int connection, int index, lgLcdDeviceDesc *description);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdOpenWrap(lgLcdOpenContext *ctx);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdCloseWrap(int device);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdReadSoftButtonsWrap(int device, DWORD *buttons);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdUpdateBitmapWrap(int device, lgLcdBitmapHeader *bitmap, DWORD priority);
extern "C" __declspec(dllexport) DWORD  _cdecl lgLcdSetAsLCDForegroundAppWrap(int device, int foregroundYesNoFlag);

stdafx.cpp

    #include "stdafx.h"
    // stdafx.h : Includedatei für Standardsystem-Includedateien
// oder häufig verwendete projektspezifische Includedateien,
// die nur in unregelmäßigen Abständen geändert werden.
//

#pragma once

// Ändern Sie folgende Definitionen für Plattformen, die älter als die unten angegebenen sind.
// In MSDN finden Sie die neuesten Informationen über die entsprechenden Werte für die unterschiedlichen Plattformen.
#ifndef WINVER              // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.
#define WINVER 0x0501       // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
#endif

#ifndef _WIN32_WINNT        // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.                   
#define _WIN32_WINNT 0x0501 // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
#endif                      

#ifndef _WIN32_WINDOWS      // Lassen Sie die Verwendung spezifischer Features von Windows 98 oder später zu.
#define _WIN32_WINDOWS 0x0410 // Ändern Sie dies in den geeigneten Wert für Windows Me oder höher.
#endif

#ifndef _WIN32_IE           // Lassen Sie die Verwendung spezifischer Features von IE 6.0 oder später zu.
#define _WIN32_IE 0x0600    // Ändern Sie dies in den geeigneten Wert für andere Versionen von IE.
#endif

#define WIN32_LEAN_AND_MEAN     // Selten verwendete Teile der Windows-Header nicht einbinden.
// Windows-Headerdateien:
#include <windows.h>

德尔福代码:

DLLHandle := LoadLibrary('lgLcdWrapperX64.dll');
  if DLLHandle = 0 then Exit(False);

  @lgLcdInit       := GetProcAddress(dllHandle, 'lgLcdInitWrap');
  if (not Assigned(lgLcdInit)) then ShowMessage(SysErrorMessage(GetLastError));

2 个答案:

答案 0 :(得分:2)

  

我收到错误“无法找到指定的模块

这不是GetProcAddress产生的错误,您可以从LoadLibrary()获取该错误。错误代码126. GetProcAddress失败,错误127“无法找到指定的过程”。所以检查你的错误处理代码,它可能有一个bug。并且三重检查您是否使用了正确的DLL路径名,并且正确部署了相关的DLL,例如CRT dll。

唯一的其他相关信息是应用于64位DLL中的导出函数的名称修饰。您的客户端代码之前肯定使用了类似“_lgLcdInitWrap”的名称,前导下划线表示__cdecl调用约定生效。 64位代码很幸运地与调用约定无关,只有一个。因此,出口不再装饰,它将只是简单的“lgLcdInitWrap”。使用dumpbin.exe / exports或depends.exe等工具肯定会看到的东西。

答案 1 :(得分:1)

发现了这个问题。当我在VS2010中添加x64平台时,它设置了2个导致整个问题的设置:

项目选项&gt;链接器&gt;高级&gt; - 随机基地址 - 数据执行保护(DEP)

禁用这两个设置修复它。

enter image description here