wafuの技術

技術習得の努力メモです。

Rubyでfiddle(2) オリジナルのDLLを使う

Rubyのfiddleを使って、DLLを使ってみました。

思わぬところではまりました。

 

最初にC++でメインとDLLを作り確認しました。

そのDLLをRubyで呼び出しましたが、エラーになります。

 

・エラー内容1

in `import_function': cannot find the function: dllfunc() (Fiddle::DLError)

これは、関数が発見できないようです。

dumpbin /exports dlltest.dll

・・・・

        1    0 00001000 ?dllfunc@@YAHH@Z

・・・・

原因はわかりません。

C言語では、DLLの呼び出しに問題がありません。

結論は、

__declspec(dllexport) int dllfunc(int);

では、だめで、

/extern "C" {
    __declspec(dllexport) int __stdcall dllfunc (int a);
}

と書く必要があったようです。

これは、C++でCの記述方法を指定するようです。

 

・エラー内容2

in `initialize': No such file or directory (Fiddle::DLError)

これは、DLLの場所が発見できなかったものです。

RubyInstaller::Runtime.add_dll_directory("./")

を追加して、DLLの場所を追加することで対応できます。

 

完成品です。

C(C++)で呼び出す場合

■メイン関数

#define UNICODE
#include <windows.h>
#pragma comment(lib,"user32.lib")


extern "C" {
        __declspec(dllexport) int __stdcall dllfunc (int a);
}

BOOL WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{

        dllfunc(100);

        return TRUE;
}

 

■DLL側

#define UNICODE
#include <windows.h>
#pragma comment(lib,"user32.lib")

extern "C" {
        __declspec(dllexport) int __stdcall dllfunc (int a);
}

 

BOOL WINAPI DllMain(HINSTANCE,DWORD,LPVOID)
{
        return TRUE;
}

__declspec(dllexport) int dllfunc(int x)
{
        wchar_t aa[512];
        wsprintf(aa,L"%d",x);

        MessageBox(NULL,aa,L"info",MB_OK);
        return TRUE;
}

 

Rubyで上記のDLL(dlltest.dll)を呼び出す。

Rubyのメイン

require 'fiddle'
require 'fiddle/import'
RubyInstaller::Runtime.add_dll_directory("./")

module Dlltest
    extend Fiddle::Importer
    dlload "./dlltest.dll"
        extern 'int dllfunc(int)'

end

 

require 'pp'

Dlltest::dllfunc(20)