0

ネイティブの fprint() ox 関数を介して、外部の c++ dll で作成されたファイルに書き込もうとしています。

私のC++コードは(C.BosのGnuDrawパッケージのsrcコードに触発された)です:

#define OxSetOpenFile(pv,i,d,f) (pv)[i].type = OX_FILE, (pv)[i].t.ioval.fp = d, (pv)[i].t.ioval.fmode = f
extern "C" void OXCALL fopen_C(OxVALUE *rtn, OxVALUE *pv, int cArg)
{
    char *sFile;
    FILE *fh;

    if (cArg != 1)
        OxRunError(ER_ARGS, NULL);

    OxLibCheckType(OX_STRING, pv, 0, 0);
    sFile = OxStr(pv, 0);
    fh = fopen(sFile, "w");

    if (fh == NULL)
        OxRunErrorMessage("Oops, I can't open the file");
    OxSetOpenFile(rtn, 0, fh, 162); //162 is found in the gnudraw src code 
}

Visual Studio 2015 で dll をビルドしましたが、ox からこのファイルに書き込めません。次の Ox コードは fprint() 関数でクラッシュします。

main()
{                        
    decl fh = fopen_C("test.txt");  
    if(!isfile(fh))
        oxrunerror("not file", 0);

    fprint(fh, "test text");  /// crash here
}

次のエラー メッセージが表示されました: "Debug Assertion Error" in close.cpp Expression (_osfile(fh) & FOPEN) 。

同様の投稿 ( here ) を見つけましたが、答え ( /MTd または /MDd を使用する - つまり、ランタイムを変更する) は機能しません。この問題は、C で新しい fprintf 関数を作成し、Ox から呼び出すことで解決できます (機能します) が、ネイティブの ox fprint 関数を使用することをお勧めします。私は、この問題はこれに、そして最後に次の質問にリンクできると思います: how to pass a file pointer from c from ox in windows ?

4

1 に答える 1

1

最後に、それは不可能だと思います。これは、いわゆるDll 境界制限が原因です。ファイル ハンドルは、コンパイル時に使用される C ランタイム ライブラリに応じて異なる方法で実装されます。明らかに、ファイル ポインタを渡すことはできますが、ファイル ハンドルの構造 (その CRT 構造) は Ox によって認識されません。

次に、私の dll が、ox のコンパイルに使用される C ランタイム ライブラリの正確に同じバージョンに対してコンパイルされない限り、動作しません。これは、C ライブラリと動的にリンクすることで克服できますが、公式の ox dll (oxwin.dll) は静的リンケージでコンパイルされているため (ヘッダー「Ox Professional version 7.10 (Windows_64/U/ MT )」に示されているように)、そうではありません。オプション。したがって、DLL をコンパイルするためにどのオプションを使用しても、Ox は常に独自の CRT ライブラリのコピーと独自のヒープ マネージャーを保持します。

最後に、外部 dll (Windows 用) で開いているファイルに書き込む最良の方法は、新しい C 関数を作成することだと思います: fprint_dll() は、ファイルを開いたり閉じたりするものと同じ dll にあり、それを呼び出します。牛。

基本的に、「ネイティブ」dll の外部でファイル ハンドルを使用して I/O 操作を実行しないようにします。

も参照してください。

https://support.microsoft.com/en-us/kb/140584

C ランタイム オブジェクト、dll 境界

于 2015-12-29T11:18:51.980 に答える