2011-07-31 13 views
1

私は、MinGWツールチェーンを使用してQT Creatorを使用してC++で書かれた新しいプログラミング言語のFFIをサポートしようとしています。 MinGWでlibffiを使用してWindows APIを呼び出す

は、私がここで見つけるlibffiのカスタムビルドのバージョンを使用し、これを行うには: http://ftp.gnome.org/pub/GNOME/binaries/win32/dependencies/libffi-dev_3.0.6-1_win32.zip

私も別のビルドでそれを試してみました:http://pkgs.org/fedora-14/fedora-updates-i386/mingw32-libffi-3.0.9-1.fc14.noarch.rpm.htmlをするために必要なファイルを、Linux上でSRPMファイルをダウンロードし、それを抽出し、コピーすることで、 Windowsパーティション。

とにかく、必要なヘッダーファイルをインクルードし、プロジェクトにインポートライブラリを追加し、アプリケーションの.exeの横に.dllを置くと、コンパイルして実行し、MessageBeep()を正常に呼び出します。私は次にMessageBoxA()でそれを試しましたが、クラッシュし続けます。デバッガは多くの有用な情報を提供していないようです(編集:MessageBoxA への呼び出しはになりました)。

私の言語の詳細から問題を切り分けるために、私は以下のコードの結果として、すべてのパラメータを自分自身で埋めて手動でMessageBoxAを呼び出そうとしましたが、依然としてクラッシュします。

QT Creator/MinGWの下で実行して実際にメッセージボックスを表示するには、以下のコードスニペットを取得するにはどうすればよいですか?

#include "libffi/include/ffi.h" 
#include <QLibrary> 

void testMessageBox() 
{ 
    int n = 4; 
    ffi_cif cif; 
    ffi_type **ffi_argTypes = new ffi_type*[n]; 
    void **values = new void*[n]; 

    values[0] = new ulong(0); 
    values[1] = (void *) "hello"; 
    values[2] = (void *) "mommy"; 
    values[3] = new int32_t(0); 

    ffi_argTypes[0] = &ffi_type_ulong; 
    ffi_argTypes[1] = &ffi_type_pointer; 
    ffi_argTypes[2] = &ffi_type_pointer; 
    ffi_argTypes[3] = &ffi_type_uint32; 

    ffi_type *c_retType = &ffi_type_sint32; 
    int32_t rc; // return value 

    if (ffi_prep_cif(&cif, FFI_STDCALL, n, c_retType, ffi_argTypes) == FFI_OK) 
    { 
     QLibrary lib("user32.dll"); 
     lib.load(); 
     void *msgbox = lib.resolve("MessageBoxA"); 
     ffi_call(&cif, (void (*)()) msgbox, &rc, values); 
    } 
} 

答えて

2

値の代わりに値配列にアドレスを渡す必要があります。文字列を渡すとき、私がchar *値そのものを渡す代わりに、変数に入れて、あなたが行ったように、変数のアドレスを送信:にMinGW64の下で動作するコードは

#include <stdio.h> 
    #include <ffi.h> 
    #include <Windows.h> 
    int main() 
    { 

    ffi_cif cif; 
      HINSTANCE dllHandle = LoadLibrary("user32.dll"); 

      int n = 4;  

      ffi_type *ffi_argTypes[4]; 
      void *values[4]; 
      UINT64 a=0; 
      UINT32 b=0; 
      TCHAR* s1= "hello"; 
      TCHAR* s2= "hello2"; 
      values[0] = &a; 
      values[1] = &s1; 
      values[2] = &s2; 
      values[3] = &b;  
      ffi_argTypes[0] = &ffi_type_uint64;  
      ffi_argTypes[1] = &ffi_type_pointer;  
      ffi_argTypes[2] = &ffi_type_pointer;  
      ffi_argTypes[3] = &ffi_type_uint; 
      ffi_type *c_retType = &ffi_type_sint;  
      ffi_type rc; // return value  
      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &ffi_type_sint, ffi_argTypes) == FFI_OK) { 


       ffi_call(&cif, FFI_FN(GetProcAddress(dllHandle,"MessageBoxA")), &rc, values); 
      } 


     return 0; 
    } 
+0

問題が何かをしています。今それは適切に動作します。私はあなたのコードを読んでからそれを発見したので、とても感謝します! (私のコードでは、値の配列は動的に割り当てられ、 'values'はダブル​​ポインタです - それは不要です - パラメータとして '値'を送り、そのアドレスは大丈夫でした)。 –

関連する問題