0

C++ Win32 コンソール アプリから空の C dll で関数 long *Test(int) を呼び出そうとしています。dll は QSIWrapperUMeLt.dll と呼ばれます。コンソール アプリケーションをビルドしようとすると、次の出力が得られます。

 adding resource. type:MANIFEST, name:1, language:0x0409, flags:0x30, size:406
1>TestPlatform.obj : error LNK2019: unresolved external symbol _Test referenced in function _wmain
1>C:\Users\Deven Bryant\Desktop\temp version\TestPlatform\Debug\TestPlatform.exe : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED. 

コンソール アプリから QSIWrapperUMeLt dll を呼び出すために行ったことは次のとおりです。dllでは、関数定義にextern "C"and属性を含めました。__declspec(dllexport)dll とコンソール アプリの両方が Win32 用にビルドするように設定されています。プロジェクト設定でdllがcコードとしてコンパイルされるように設定されていることを確認しました。コンソール アプリ#includeQSIWrapperUMeLt.hファイルを編集し、プリ プロセッサ ディレクティブを使用するように変更__declspec(dllexport)しました。__declspec(dllimport)また、.dll を使用して dll にリンクしました#pragma comment(lib, "DLLTutorial.lib")。QSIWrapperUMeLt ライブラリ ファイル、ヘッダー ファイル、および dll は、コンソール アプリのプロジェクト フォルダーにあります。

以下に、dll のヘッダー ファイル、コンソール アプリの cpp ファイル、シンボル テーブル、および QSIWrapperUMeLt.dll で実行したときに dumpbin によって検出されるエクスポート関数を提供しました。

また、明示的なリンク ルートを試しましたが、ロード ライブラリを呼び出すと null ポインターが返されます。

私が間違っていることについてのアイデアは大歓迎です。

QSIWrapperUMELt.h

#include <Windows.h>
//#pragma comment(lib, "DLLTutorial.lib")

#ifdef EXPORT
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport);
#endif

#define BOOL int
#define TRUE 1
#define FLSE 0

typedef enum
{
    initialize = 0,
    setup,
    capture,
    temperature,
    close,
    getimagedata
} CallStates;

typedef struct ReturnedValues
{
    BOOL initialized, imagereadyflag, exposuredone;
    long** imagedata;
    double Temperature;
}ReturnedValues;

typedef struct CameraData
{
    short Mode;
    short Binning;
    int Exposure;
    int Top;
    int Left;
    int Height;  //ROIH
    int Width;   //ROIW
    int CoolerSetpoint;
    int Temperature;
}CameraData;

typedef void (*callFunction)(CameraData camdata, ReturnedValues *retvals);


DECLSPEC ReturnedValues *retvals;
callFunction pcallFunction;
HINSTANCE hlib;
CameraData camdata;

#ifdef __cplusplus 
extern "C"
{
#endif
DECLSPEC ReturnedValues entryPoint();
DECLSPEC long *Test(int length);
#ifdef __cplusplus
}
#endif

TestPlatform.cpp (コンソール アプリ) 私はこれから Test() を呼び出そうとしています

#include "stdafx.h"
#include <Windows.h>
#include <iostream> 
#include <conio.h>
#include <strsafe.h>
#define IMPORT
//#define EXPLICIT
using namespace std;
#ifndef EXPLICIT
#include "QSIWrapperUMeLt.h"
//#include "QSIAccessor.h"
#pragma comment(lib, "QSIWrapperUMeLt.lib")
//#pragma comment(lib, "QSIAccessorUMEmpty.lib")
#endif

#ifdef EXPLICIT
typedef long *(*Test)(int length);
HINSTANCE hinstlib;
Test pTest;
#endif

void ErrorExit(LPTSTR lpszFunction);

int _tmain(int argc, _TCHAR* argv[])
{
    int temp = 1;
    long *data;
#ifdef EXPLICIT
    hinstlib = LoadLibrary((LPCWSTR)"QSIWrapperUMeLt.dll");
    if(hinstlib)
    {
#endif
        int i;
        cout << "hinstlib was successfully initialized" << endl;
#ifdef EXPLICIT
        pTest = (Test)GetProcAddress(hinstlib, (LPCSTR)"Test");
        data = pTest(10000);
#else
        data = Test(1000);
        //callFunction(CameraData *camdata, ReturnedValues *retvals);
#endif
        for(i = 0; i < 20; i++)
        {
            cout << data[i] << endl;
        }
#ifdef EXPLICIT
    }
    else
    {
        ErrorExit(TEXT("LoadLibrary"));
    }
    FreeLibrary(hinstlib);
#endif
    getch();
    return 0;
}

void ErrorExit(LPTSTR lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw); 
}

QSIWrapperUMelt SYMBOL TABLES

            C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin>dumpbin /SYMBOLS "C:\Users\...\Desktop\temp version\C_C++libs\QSIWrapperUMeLt\Debug\QSIWrapperUMeLt.li
            b"
            Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
            Copyright (C) Microsoft Corporation.  All rights reserved.


            Dump of file C:\Users\Deven Bryant\Desktop\temp version\C_C++libs\QSIWrapperUMeLt\Debug\QSIWrapperUMeLt.lib

            File Type: LIBRARY

            COFF SYMBOL TABLE
            000 009C766F ABS    notype       Static       | @comp.id
            001 00000000 SECT2  notype       External     | __IMPORT_DESCRIPTOR_QSIWrapperUMeLt
            002 C0000040 SECT2  notype       Section      | .idata$2
            003 00000000 SECT3  notype       Static       | .idata$6
            004 C0000040 UNDEF  notype       Section      | .idata$4
            005 C0000040 UNDEF  notype       Section      | .idata$5
            006 00000000 UNDEF  notype       External     | __NULL_IMPORT_DESCRIPTOR
            007 00000000 UNDEF  notype       External     | ¦QSIWrapperUMeLt_NULL_THUNK_DATA

            String Table Size = 0x62 bytes

            COFF SYMBOL TABLE
            000 009C766F ABS    notype       Static       | @comp.id
            001 00000000 SECT2  notype       External     | __NULL_IMPORT_DESCRIPTOR

            String Table Size = 0x1D bytes

            COFF SYMBOL TABLE
            000 009C766F ABS    notype       Static       | @comp.id
            001 00000000 SECT2  notype       External     | ¦QSIWrapperUMeLt_NULL_THUNK_DATA

            String Table Size = 0x25 bytes

              Summary

                      DB .debug$S
                      14 .idata$2
                      14 .idata$3
                       4 .idata$4
                       4 .idata$5
                      14 .idata$6

QSIWrapperUMelt EXPORTS

            C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin>dumpbin /EXPORTS "C:\Users\...\Desktop\temp version\C_C++libs\QSIWrapperUMeLt\Debug\QSIWrapperUMeLt.dl
            l"
            Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
            Copyright (C) Microsoft Corporation.  All rights reserved.


            Dump of file C:\Users\Deven Bryant\Desktop\temp version\C_C++libs\QSIWrapperUMeLt\Debug\QSIWrapperUMeLt.dll

            File Type: DLL

              Section contains the following exports for QSIWrapperUMeLt.dll

                00000000 characteristics
                500E089F time date stamp Mon Jul 23 19:29:51 2012
                    0.00 version
                       1 ordinal base
                       3 number of functions
                       3 number of names

                ordinal hint RVA      name

                      1    0 00011127 Test = @ILT+290(_Test)
                      2    1 0001102D entryPoint = @ILT+40(_entryPoint)
                      3    2 00017580 retvals = _retvals

              Summary

                    1000 .data
                    1000 .idata
                    2000 .rdata
                    1000 .reloc
                    1000 .rsrc
                    4000 .text
                   10000 .textbss
4

1 に答える 1

1

EXPLICIT が定義されていない場合、問題の理由がわかりません。ただし、LoadLibrary の引数には次の問題があります。

(LPCWSTR)"QSIWrapperUMeLt.dll"

ANSI 文字列 "QSIWrapperUMeLt.dll" は、1 バイトの NUL で終了する一連の 1 バイト文字を含むバイト配列です。関数の引数などの式で使用すると、式は最初の文字へのポインター、char* または LPSTR 型のポインターに変換されます。

LPCWSTR 型にポインターをキャストします。ただし、ポインターは引き続き、1 バイトの NUL で終了する一連の 1 バイト文字を指します。

Unicode 文字列が必要なため、次のようにできます。

L"QSIWrapperUMeLt.dll"

または、将来コードが必要になる可能性がある場合に、ANSI または Unicode との互換性を確保するため:

_T("QSIWrapperUMeLt.dll")
于 2012-07-26T00:40:51.183 に答える