Вызов Windows API с помощью libffi на MinGW - PullRequest
1 голос
/ 31 июля 2011

Я пытаюсь получить поддержку FFI для моего нового языка программирования, который написан на C ++ с использованием QT Creator с использованием набора инструментов MinGW.

Для этого я использовал пользовательскую версию 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, загрузив файл SRPM в Linux, распаковав его и скопировав необходимые файлы в раздел Windows.

В любом случае, я включил требуемый заголовочный файл, добавил библиотеку импорта в проект и поместил .dll рядом с .exe приложения, он компилируется и запускается, успешно вызывая 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);
    }
}

1 Ответ

2 голосов
/ 02 августа 2011

вы должны передать адрес в массив значений вместо значений. рабочий код под 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;
     }
...