You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby通过FFI调用共享库时libapi.so符号无法识别的问题

Fixing "undefined symbol: start_client" in FFI Call

Alright, let's break down why this error happens when using Ruby FFI but works perfectly with direct C calls, and walk through the fixes.

Root Cause

When you compile a C executable that calls start_client from libapi.so, the linker adds a dependency on libapi.so to the executable. So when you run the C program, the dynamic linker automatically loads libapi.so and resolves the start_client symbol without issue.

But if your web_client.so was compiled without linking against libapi.so, it won’t have that dependency recorded. When FFI loads web_client.so, the dynamic linker can’t find start_client because libapi.so isn’t loaded into the process space.

The cleanest fix is to ensure web_client.so explicitly links against libapi.so during compilation. Update your Makefile rule for web_client.so to include the necessary library flags:

# Example Makefile rule
web_client.so: web_client.c
	gcc -fPIC -shared -o $@ $< -L/path/to/libapi_directory -lapi

Let’s break down the key flags:

  • -fPIC: Generates position-independent code (required for shared libraries to work across different memory addresses).
  • -shared: Tells the compiler to output a shared library instead of a standalone executable.
  • -L/path/to/libapi_directory: Points to the folder where libapi.so lives (skip this if it’s in a standard system path like /usr/lib).
  • -lapi: Links against libapi.so (the linker looks for libapi.so when given -lapi).

After rebuilding, run ldd /path/to/web_client.so — you should see libapi.so listed as a dependency. Now when FFI loads web_client.so, the dynamic linker will automatically load libapi.so and resolve the start_client symbol.

Solution 2: Explicitly Load libapi.so in Your Ruby FFI Code

If you can’t modify the web_client.so compilation (or prefer not to), you can load libapi.so directly in your Ruby code before loading web_client.so. This ensures the start_client symbol is present in the process space when web_client.so is loaded.

Here’s how to adjust your Client.rb:

require 'ffi'

# First, load libapi.so to make its symbols available to the process
module LibAPI
  extend FFI::Library
  ffi_lib '/path/to/libapi.so'
  # Declare the function signature for start_client (adjust params/return type to match your actual code)
  attach_function :start_client, [], :void
end

# Now load web_client.so — it can resolve start_client since LibAPI is already loaded
module WebClient
  extend FFI::Library
  ffi_lib '/path/to/web_client.so'
  attach_function :send_from_web, [], :void # Adjust signature to match your function
end

class Client
  def self.send_from_web
    WebClient.send_from_web
  end
end

Solution 3: Ensure libapi.so is Findable by the Dynamic Linker

If libapi.so lives in a non-standard directory, you might need to tell the dynamic linker where to find it when running your Ruby script. Set the LD_LIBRARY_PATH environment variable before executing the script:

export LD_LIBRARY_PATH=/path/to/libapi_directory:$LD_LIBRARY_PATH
ruby Client.rb

This makes the dynamic linker search the specified directory for libapi.so when loading shared libraries.

内容的提问来源于stack exchange,提问作者Daniel Mur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:29:05