Skip to content

Commit b68f6b3

Browse files
committed
Find proc address from linked DLLs on windows
1 parent 51eb37d commit b68f6b3

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

src/cfunc_call.c

+34-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,34 @@
1717
#include <stdbool.h>
1818
#include "ffi.h"
1919

20+
#ifdef _WIN32
21+
#include <windows.h>
22+
static void*
23+
get_proc_address(const char* funcname)
24+
{
25+
HINSTANCE hInst = GetModuleHandle(NULL);
26+
PBYTE pImage = (PBYTE) hInst;
27+
PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER) hInst;
28+
PIMAGE_NT_HEADERS pPE;
29+
PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
30+
31+
if (pDOS->e_magic != IMAGE_DOS_SIGNATURE)
32+
return NULL;
33+
pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew);
34+
if (pPE->Signature != IMAGE_NT_SIGNATURE)
35+
return NULL;
36+
pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage
37+
+ pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
38+
for (; pImpDesc->FirstThunk; ++pImpDesc) {
39+
HINSTANCE hLib = LoadLibrary((const char*)(pImage + pImpDesc->Name));
40+
if (hLib) {
41+
void* p = GetProcAddress(hLib, "strcpy");
42+
if (p) return p;
43+
}
44+
}
45+
return NULL;
46+
}
47+
#endif
2048

2149
static mrb_value
2250
cfunc_call(mrb_state *mrb, mrb_value self)
@@ -25,14 +53,18 @@ cfunc_call(mrb_state *mrb, mrb_value self)
2553
mrb_value mresult_type, mname, *margs;
2654
void **values = NULL;
2755
ffi_type **args = NULL;
28-
56+
2957
mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc);
30-
58+
3159
void *fp = NULL;
3260
if(mrb_string_p(mname) || mrb_symbol_p(mname)) {
61+
#ifndef _WIN32
3362
void *dlh = dlopen(NULL, RTLD_LAZY);
3463
fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname));
3564
dlclose(dlh);
65+
#else
66+
fp = get_proc_address(mrb_string_value_ptr(mrb, mname));
67+
#endif
3668

3769
if(fp == NULL) {
3870
mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname));

test/call_strcpy.rb

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
mobiruby_test "CFunc::call_strcpy" do
2-
skip if CFunc::Platform.is_win32?
3-
42
ptr = CFunc::Pointer.malloc(12)
53

6-
result = CFunc::call(CFunc::Pointer, "strcpy", ptr, "Hello")
4+
if CFunc::Platform.is_win32?
5+
result = CFunc::libcall(CFunc::Pointer, "msvcrt.dll", "strcpy", ptr, "Hello")
6+
else
7+
result = CFunc::call(CFunc::Pointer, "strcpy", ptr, "Hello")
8+
end
79
assert_equal "Hello", result.to_s
810
assert_equal "Hello", ptr.to_s
911

10-
result = CFunc::call(CFunc::Pointer, :strcat, ptr, " World")
12+
if CFunc::Platform.is_win32?
13+
result = CFunc::libcall(CFunc::Pointer, "msvcrt.dll", :strcat, ptr, " World")
14+
else
15+
result = CFunc::call(CFunc::Pointer, :strcat, ptr, " World")
16+
end
1117
assert_equal "Hello World", result.to_s
1218
assert_equal "Hello World", ptr.to_s
1319
end

test/string1.rb

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
mobiruby_test "CFunc::String1" do
2-
skip if CFunc::Platform.is_win32?
3-
42
str = "STRING"
53
ptr = CFunc::Pointer.malloc(7)
64

0 commit comments

Comments
 (0)