Techioz Blog

RubyでFFI::Libraryを使用してバイナリ.soライブラリをアンロードまたは指定するにはどうすればよいですか?

概要

libcurlライブラリを行でロードするethon gemがあります。

ffi_lib_flags :now, :global
ffi_lib ['ibcurl.so', 'libcurl.so.4']
extend Ethon::Curls::Functions # it attaches functions from libcurl

モンキーパッチを作ります

ffi_lib_flags :now, :global
ffi_lib '/home/myuser/libs/libcurl.so'
attach_function :easy_impersonate, :curl_easy_impersonate, [:pointer, :string, :int], :int # attach custom function from patched libcurl
extend Ethon::Curls::Functions # it attaches default functions from patched libcurl

FFI は、curl_easy_impersonate 関数を見つけましたが、それを呼び出すと、コード 48 が返されます (libcurl ドキュメントでは、そのような関数が見つからなかったことを意味します)。

ただし、gem ffi_lib [‘libcurl.so’, ‘libcurl.so.4’] の行を ffi_lib ‘/home/myuser/libs/libcurl.so’ に直接置き換えると、この関数を呼び出すと 0 が返され、機能します。私がそうしたいように。これは、FFI が gem によってロードされたライブラリに最初にアクセスするためだと私は考えています。

質問: FFI を使用してこのライブラリをアンロードする方法、または関数呼び出しに使用するライブラリを明示的に指定する方法はありますか?

追伸モンキーパッチでやりたいのですが、たった1行を変更するためにgemをフォークしたくありません。本番環境でサポートするには不便です。

添付されたメソッドを削除しようとし、削除するメソッド ffi_libraries を持つ libcurl ライブラリ オブジェクトを見つけ、ロードされた libcurl の痕跡を見つけようとしましたが、見つかりませんでした。

解決策

FFI ライブラリには、ロードされたライブラリをアンロードする方法が提供されていないと思います。

ライブラリを「アンロード」する必要がある場合は、FFI::Library 自体の外部でこれを処理する必要があります。 Ruby プロセスを再起動してみてください。

または、FFI バインディングがロードされる前にこれを試すこともできます。LD_LIBRARY_PATH 環境変数を設定して、パッチを適用した libcurl.so が配置されているディレクトリを指定することもできます。これにより、ローダーが使用するライブラリ検索パスが変更され、Ruby スクリプトが LD_LIBRARY_PATH の指定されたディレクトリからパッチが適用された libcurl.so を取得できるようになります。