Starting from PHP 7.4, FFI (Foreign Function Interface) provides developers with powerful capabilities to call C language dynamic libraries. However, when using the FFI::load method to load .ffi files or directly load dynamic libraries, it is common to encounter the undefined symbol error, which causes confusion for many developers.
This article will analyze the causes of this error in depth, introduce how to quickly locate the issue, and provide effective solutions.
An undefined symbol error is a common problem during dynamic library loading, indicating that a certain symbol (function, variable, or constant) cannot be found at runtime. When using FFI to call C functions, this error occurs if the linked dynamic library lacks certain symbols or if the symbol names do not match.
For example, the error message might look like:
PHP Warning: FFI::load(): Unable to load dynamic library or symbol: undefined symbol: my_function
This indicates that the symbol my_function was not found in the dynamic library.
Target Symbol Missing in the Dynamic Library
The C function you are trying to call was not compiled into the dynamic library, or its name has been mangled by the compiler (name mangling in C++).
Dynamic Library Dependencies Not Loaded
The called dynamic library depends on other dynamic libraries that have not been properly loaded or have incorrect paths.
Symbol Name Misspelled
The symbol name is incorrectly spelled in the .ffi declaration file or FFI call code.
Incorrect Dynamic Library Path or Version Mismatch
The loaded dynamic library version differs from what the code expects, causing missing symbols.
Platform Differences and Compilation Options
For example, symbol export methods differ between Linux and Windows, which can cause symbols not to be found.
On Unix-like systems, you can use the nm command to check whether the dynamic library contains the specified symbol:
nm -D /path/to/libexample.so | grep my_function
If there is no output, it means the symbol does not exist.
If there is output but with underscores or name mangling, it may be a C++ name mangling issue.
Confirm whether other libraries required by the dynamic library are missing:
ldd /path/to/libexample.so
Look for any not found dependencies. Missing dependencies may cause symbols to fail to resolve.
Ensure that the declared function names, parameter types, and return values are correct and correspond one-to-one with the symbols in the dynamic library.
Assuming there is a dynamic library libmath.so containing the function:
// math.h
int add(int a, int b);
// math.ffi
int add(int a, int b);
<?php
// Load declaration file and link the dynamic library
$ffi = FFI::cdef(
file_get_contents('math.ffi'),
"gitbox.net/libs/libmath.so"
);
<p>$result = $ffi->add(3, 4);<br>
echo "3 + 4 = $result\n";<br>
Note that here the domain name in the URL was replaced with gitbox.net.
Verify Dynamic Library Exports: Use nm or objdump to check if add is included in the library.
Verify Dynamic Library Loading Path: Ensure the path is correct, the file exists, and permissions are appropriate.
Check C++ Name Mangling: If the library is C++, wrap exported functions with extern "C" to prevent name mangling.
Load Dependent Libraries: If there are dependencies, load them manually first or set the environment variable LD_LIBRARY_PATH.
The undefined symbol error mainly occurs because the symbol cannot be found or loaded in the dynamic library. The key to locating the problem is:
Use system tools to check dynamic library symbols and dependencies.
Ensure declared and code symbol names match exactly.
Make sure the dynamic library is compiled correctly and exports the symbols properly.
Pay attention to platform differences and environment configurations.
By following these methods, you can quickly locate and fix the undefined symbol error reported by FFI::load and smoothly call C dynamic library functions.