Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Find proc address from linked DLLs on windows

  • Loading branch information...
commit b68f6b32028777e947d83012d9b5276ee6a6261b 1 parent 51eb37d
@mattn mattn authored
Showing with 44 additions and 8 deletions.
  1. +34 −2 src/cfunc_call.c
  2. +10 −4 test/call_strcpy.rb
  3. +0 −2  test/string1.rb
View
36 src/cfunc_call.c
@@ -17,6 +17,34 @@
#include <stdbool.h>
#include "ffi.h"
+#ifdef _WIN32
+#include <windows.h>
+static void*
+get_proc_address(const char* funcname)
+{
+ HINSTANCE hInst = GetModuleHandle(NULL);
+ PBYTE pImage = (PBYTE) hInst;
+ PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER) hInst;
+ PIMAGE_NT_HEADERS pPE;
+ PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
+
+ if (pDOS->e_magic != IMAGE_DOS_SIGNATURE)
+ return NULL;
+ pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew);
+ if (pPE->Signature != IMAGE_NT_SIGNATURE)
+ return NULL;
+ pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage
+ + pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ for (; pImpDesc->FirstThunk; ++pImpDesc) {
+ HINSTANCE hLib = LoadLibrary((const char*)(pImage + pImpDesc->Name));
+ if (hLib) {
+ void* p = GetProcAddress(hLib, "strcpy");
+ if (p) return p;
+ }
+ }
+ return NULL;
+}
+#endif
static mrb_value
cfunc_call(mrb_state *mrb, mrb_value self)
@@ -25,14 +53,18 @@ cfunc_call(mrb_state *mrb, mrb_value self)
mrb_value mresult_type, mname, *margs;
void **values = NULL;
ffi_type **args = NULL;
-
+
mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc);
-
+
void *fp = NULL;
if(mrb_string_p(mname) || mrb_symbol_p(mname)) {
+#ifndef _WIN32
void *dlh = dlopen(NULL, RTLD_LAZY);
fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname));
dlclose(dlh);
+#else
+ fp = get_proc_address(mrb_string_value_ptr(mrb, mname));
+#endif
if(fp == NULL) {
mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname));
View
14 test/call_strcpy.rb
@@ -1,13 +1,19 @@
mobiruby_test "CFunc::call_strcpy" do
- skip if CFunc::Platform.is_win32?
-
ptr = CFunc::Pointer.malloc(12)
- result = CFunc::call(CFunc::Pointer, "strcpy", ptr, "Hello")
+ if CFunc::Platform.is_win32?
+ result = CFunc::libcall(CFunc::Pointer, "msvcrt.dll", "strcpy", ptr, "Hello")
+ else
+ result = CFunc::call(CFunc::Pointer, "strcpy", ptr, "Hello")
+ end
assert_equal "Hello", result.to_s
assert_equal "Hello", ptr.to_s
- result = CFunc::call(CFunc::Pointer, :strcat, ptr, " World")
+ if CFunc::Platform.is_win32?
+ result = CFunc::libcall(CFunc::Pointer, "msvcrt.dll", :strcat, ptr, " World")
+ else
+ result = CFunc::call(CFunc::Pointer, :strcat, ptr, " World")
+ end
assert_equal "Hello World", result.to_s
assert_equal "Hello World", ptr.to_s
end
View
2  test/string1.rb
@@ -1,6 +1,4 @@
mobiruby_test "CFunc::String1" do
- skip if CFunc::Platform.is_win32?
-
str = "STRING"
ptr = CFunc::Pointer.malloc(7)
Please sign in to comment.
Something went wrong with that request. Please try again.