0

私は主に Delphi 開発者であり、Logitech の G15 などの API DLL とインターフェイスしてキーボードの LCD 画面と対話する DLL ラッパーを使用しています。

数年前、ある人がこのラッパーを Delphi で使用するように作成しました。基本的には、Logitech lib とインターフェイスし、関数を Delphi にエクスポートする DLL です。正常に動作していますが、32 ビットのみでした。

ラッパーのソースを入手して 64 ビット用にコンパイルしようとしましたが、何かがおかしいです。プラットフォームを 64 ビットに設定し、それに応じて構成などを変更し (私が思うに)、ライブラリ パスを Logitech 64 ビット .lib に指定しました。

エクスポートはあるようですが、GetProcAddress を使用してロードしようとすると、「指定されたモジュールが見つかりませんでした」というエラーが表示されます。

どうしたの?

ここに画像の説明を入力

// 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>

Delphi コード:

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

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

2 に答える 2

2

「指定されたモジュールが見つかりませんでした」というエラーが表示されます

これは GetProcAddress によって生成されるエラーではなく、LoadLibrary() から取得します。エラー コード 126。GetProcAddress がエラー 127「指定されたプロシージャが見つかりませんでした」で失敗します。エラー処理コードを確認してください。おそらくバグがあります。また、DLL に正しいパス名を使用していること、および CRT dll などの依存 DLL が適切に展開されていることをトリプル チェックします。

他の唯一の関連情報は、64 ビット DLL でエクスポートされた関数に適用される名前の装飾です。あなたのクライアント コードは、以前は "_lgLcdInitWrap" のような名前を使用していました。先頭のアンダースコアは、__cdecl 呼び出し規約が有効であることを示しています。64 ビット コードは、ありがたいことに呼び出し規約にとらわれず、呼び出し規約は 1 つしかありません。したがって、エクスポートは装飾されなくなり、単純な「lgLcdInitWrap」になります。dumpbin.exe /exports や depends.exe などのツールで確実に見られるもの。

于 2012-06-23T11:49:43.810 に答える
1

問題が見つかりました。VS2010 に x64 プラットフォームを追加すると、問題全体を引き起こす 2 つの設定が設定されました。

プロジェクト オプション > リンカ > 詳細設定 > - ランダム化されたベース アドレス - データ実行防止 (DEP)

これら2つの設定を無効にすると修正されました。

ここに画像の説明を入力

于 2012-06-23T15:38:13.253 に答える