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)