summaryrefslogtreecommitdiff
path: root/ext/ffi/ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi/ffi.c')
-rw-r--r--ext/ffi/ffi.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c
index c665ad151e..552d168fd6 100644
--- a/ext/ffi/ffi.c
+++ b/ext/ffi/ffi.c
@@ -765,6 +765,38 @@ again:
}
/* }}} */
+#if defined(ZEND_WIN32) && (defined(HAVE_FFI_FASTCALL) || defined(HAVE_FFI_STDCALL))
+static size_t zend_ffi_arg_size(zend_ffi_type *type) /* {{{ */
+{
+ zend_ffi_type *arg_type;
+ size_t arg_size = 0;
+
+ ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) {
+ arg_size += ZEND_FFI_TYPE(arg_type)->size;
+ } ZEND_HASH_FOREACH_END();
+ return arg_size;
+}
+/* }}} */
+#endif
+
+static zend_always_inline zend_string *zend_ffi_mangled_func_name(zend_string *name, zend_ffi_type *type) /* {{{ */
+{
+#ifdef ZEND_WIN32
+ switch (type->func.abi) {
+# ifdef HAVE_FFI_FASTCALL
+ case FFI_FASTCALL:
+ return strpprintf(0, "@%s@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type));
+# endif
+# ifdef HAVE_FFI_STDCALL
+ case FFI_STDCALL:
+ return strpprintf(0, "_%s@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type));
+# endif
+ }
+#endif
+ return zend_string_copy(name);
+}
+/* }}} */
+
#if FFI_CLOSURES
typedef struct _zend_ffi_callback_data {
zend_fcall_info_cache fcc;
@@ -2842,7 +2874,10 @@ ZEND_METHOD(FFI, cdef) /* {{{ */
}
sym->addr = addr;
} else if (sym->kind == ZEND_FFI_SYM_FUNC) {
- addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name));
+ zend_string *mangled_name = zend_ffi_mangled_func_name(name, ZEND_FFI_TYPE(sym->type));
+
+ addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(mangled_name));
+ zend_string_release(mangled_name);
if (!addr) {
zend_throw_error(zend_ffi_exception_ce, "Failed resolving C function '%s'", ZSTR_VAL(name));
}
@@ -3172,7 +3207,10 @@ ZEND_METHOD(FFI, load) /* {{{ */
}
sym->addr = addr;
} else if (sym->kind == ZEND_FFI_SYM_FUNC) {
- addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name));
+ zend_string *mangled_name = zend_ffi_mangled_func_name(name, ZEND_FFI_TYPE(sym->type));
+
+ addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(mangled_name));
+ zend_string_release(mangled_name);
if (!addr) {
if (preload) {
zend_error(E_WARNING, "failed pre-loading '%s', cannot resolve C function '%s'", filename, ZSTR_VAL(name));