0

プラグインで拡張できる Windows 専用のゲームと、使用したい Linux ライブラリがあります。アプリケーション (Unity ゲーム) は Wine/Proton で正常に動作します。私は Winelib がこれを行うことができることを発見しました。私はUser's Guide、特に私の正確なユースケースについて言及している 5 番目のセクションに従っていました。

いくつかの試行 (winemaker から --single-target arg を削除するなど) の後、Proton デバッグ ログに STATUS_BAD_IMAGE_FORMAT と思われる c000007b が表示され続けるポイントに到達しました。

Linux ライブラリの名前を変更した (そしてそれに対してリンクした) ことに注意してください。これは、それと私のラッパーとの間の潜在的な競合を回避するためです。

私は 64 ビット バージョンのライブラリしか持っておらず、cdecl 呼び出し規約を使用して C# コードから呼び出されます。これは私がこれまでに試したことです(およびこれらの組み合わせ):

  • コンテンツを含む .spec ファイルを追加しました (最初は -arch なしで序数が異なります):
1 cdecl -arch=x86_64 LibraryFunc (long ptr ptr) LibraryFuncWine
  • ライブラリのヘッダーと .c ファイルを追加:
#include "library_header.h"
#include <windef.h> /* Part of the Wine header files */

enum ELibResult WINAPI LibraryFuncWine(Version version, struct CreateParams* params, struct ICore** result)
{
    enum ELibResult ret = LibraryFunc(version, params, result);

    return ret;
}
  • winemaker --nosource-fix --dll --nomfc -I. -L. -llinux_library .当時の使用ワインメーカーmake
  • ゲーム全体に.dll.soファイルをコピーしました
  • .dll.so ファイルを steamapps/common/Proton 5.0/dist/lib64/wine/ にコピーし、ネイティブ ライブラリを 1 つ上のレベル (lib64/) にコピーし、その他を削除しました
  • また、lib64/ の代わりに lib/ にコピーしようとしました
  • ファイルの dll オーバーライドを追加し、組み込みに設定しました
  • 参照されている DLL (odbc32、ole32、oleaut32、winspool、odbccp32) とライブラリ (uuid) をメイクファイルから削除しました。
  • --mno-cygwinコンパイラ フラグに追加する
  • -m64コンパイラ/リンカー フラグにとを追加( Wine 仕様ファイル-fPICに基づく)
  • 私も .def ファイルを作成してそれを使用しようとしました
  • --nomsvcrt引数を追加して再度 winemaker を使用し、実行しましたmake(ヘッダー ファイルには string.h が含まれています)。

Proton ログから (+module、他の人は私にそれ以上の情報を提供しませんでした):

00dc:trace:module:load_dll looking for L"Z:\\D\\a\\library\\path\\library_name" in L"Z:\\D\\gamepath;C:\\windows\\system32;C:\\windows\\system;C:\\windows;C:\\Program Files (x86)\\Steam;.;C:\\windows\\system32;C:\\windows;C:\\windows\\system32\\wbem;C:\\windows\\system32\\WindowsPowershell\\v1.0"
00dc:trace:module:get_load_order looking for L"Z:\\D\\a\\library\\path\\library_name.dll"
00dc:trace:module:get_load_order_value got standard key b for L"library_name"
00dc:trace:module:load_builtin_dll Trying built-in L"library_name.dll"
00dc:trace:module:load_so_dll loading L"\\??\\Z:\\D\\a\\library\\path\\library_name.dll" from so lib "/D/Games/SteamLibrary/steamapps/common/Proton 5.0/dist/bin/../lib64/wine/library_name.dll.so"
00dc:warn:module:load_dll Failed to load module L"Z:\\D\\a\\library\\path\\library_name"; status=c000007b

同じことが .dll の有無にかかわらず繰り返され、lib (library_name.dll、liblibrary_name、および liblibrary_name.dll) で始まります。

そのエラー コード以外に何が問題なのかについて、これ以上のログを取得できませんでした。

C# 側 (Unity が Proton で実行) では、DllNotFoundException が発生します。

ワインのバージョン (winebuild、winegcc): 5.9 (ステージング) - gcc 9.0.1

プロトン バージョン: 5.0 - wine-5.0-603-g068dee4

4

1 に答える 1

0

.soRPCのみを使用したバイナリの解決策があるかもしれません。

しかし、多く/ほとんどの Linux ライブラリにはソース コードがあるため、[ない] 特定のライブラリは何ですか? 類似した代替ライブラリはありますか? よく調べれば、バイナリ ライブラリのソース コードがあるかもしれません。

ただし、バイナリ Linux ライブラリを使用する必要があると仮定します。

ただし、これには、希望以上の作業が必要になる場合があります。 それで、あなたはこれをどれほどひどく望んでいますか?;-)

これは生産用ですか、それとも個人的な使用ですか?WinX ゲームをワインの下で動作させようとしているため、個人的な使用のみを想定しています。

.so[wine プログラムが呼び出す必要のある] パブリック API 関数の数はどれくらいですか? いくつの異なる構造体が関係していますか?

API 呼び出しと構造体ごとに、グルー/インターフェイス ルーチンを作成する必要がある場合があります。

基本的な方法は、[ある種の] RPC [リモート プロシージャ コール] メカニズムを使用することです (例) https://en.wikipedia.org/wiki/Remote_procedure_call

目的の [Linux のみ] ライブラリを組み込んだ Linux サーバーを作成します。RPC 呼び出しをライブラリの API 呼び出しに変換するラッパー ルーチンを作成します。

ゲームでは、プラグインがサーバーに送信される RPC 呼び出しを発行し、サーバーが処理を行い、結果を返します。

そのために役立つツールがいくつかあります (例: rpcgen)

通常、RPC はネットワーク/ソケット接続を介して実行されます。あなたの目的のために、これはローカルホスト上またはAF_UNIX接続を使用することができます。多分それはあなたの目的には十分速いです。

それ以外の場合は、共有メモリ バッファー プールを確立し、それを RPC 呼び出しの補助として追加する必要があります。


アップデート:

ありがとうございます。しかし、Winelib を使用して実行できない理由について、さらに詳しい情報を提供していただけますか? ガイドには、Linuxライブラリを私のものにリンクできると書かれています。

いくつかのグルー関数を書くことができるかもしれません。これを行うと、問題が発生する可能性があります。しかし、Discord SDK で見つけたものに基づいて、これを [すべて] バイパスできる可能性があります。下記参照。


ABI の違い: WinX では最初の 4 つの引数が regs で渡され、Linux では最初の 6 つの引数が regs で渡されます。レジスターが異なります。これは、新しいスタック フレームを確立し、値を Linux の正しいレジスタに移動する「サンク」ルーチンで処理できます。参照: https://en.wikipedia.org/wiki/X86_calling_conventions

しかし、少なくとも私のマシンでは、AFAICTはwine最終的に/usr/bin/wine3232ビットの実行可能ファイルになります。ただし、Linux ライブラリは 64 ビットです。その問題は簡単には解決できません。参照: 64 ビット Linux の同じ実行可能ファイルで 64 ビットと 32 ビットの両方の命令を使用することは可能ですか? 個人的には、そうしなければならない場合は、RPC ルートを使用します。


ライブラリは 2 つの関数をエクスポートします。私が興味を持っているのは 1 つだけです。残りの機能は関数ポインタを介して行われます (これらが wine で機能するかどうかはわかりませんが、まだ機能していません)。lib は実際には Discord の Game SDK であるため、これに代わるものはありませんが、これは単なる趣味です。

サイトからダウンロードdiscord_game_sdk.zipして解凍しただけです。ソースコードのサンプルプログラムがあります。そして、必要な.hファイル。

lib/x86次のサブディレクトリがあります。discord_game_sdk.dllおよびdiscord_game_sdk.dll.lib32 ビット PE 形式のファイルです。そして、lib/x86_64サブディレクトリもあります[これには.so]があります

では、 linux の代わりに、.soこれらの PE 形式のファイルに直接リンクできますか? (例) それらはおそらくLoadLibrary


直接的な方法がない場合は、ソケットを使用できます (ただし、UNIX ソケットを作成しても同じ問題は発生しませんか? ただし、localhost は間違いなく使用できます)。

次に、これをフォールバックの位置と考えてください。

PF_INETローカルホストへのソケット呼び出しは非常に高速であり、[いくつかの「トリック」を使用して] プラグイン [の下wine] と Linux が.soリンクされている [作成した] サーバー プログラムとの間に共有メモリ空間を確立できます。

于 2020-06-01T15:35:16.080 に答える