2

関数が次のように定義された Delphi DLL があります。

function SubmitJobStringList(joblist: tStringList; var jobno: Integer): Integer;

これを C# から呼び出しています。C# には tStringList が存在しないため、最初のパラメーターを宣言するにはどうすればよいですか。私は現在、次のように宣言しています。

[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);

しかし、それを呼び出すと、メモリ アクセス違反の例外が発生します。

C#からtStringListに正しく渡す方法を知っている人はいますか?

4

7 に答える 7

13

あなたはおそらくこれで運が悪いでしょう。TStringList は単なる配列ではなく、本格的なクラスであり、正確な実装の詳細は .NET で可能なものとは異なる場合があります。Delphi VCL のソース コードを見て(つまり、お持ちであれば)、C# でクラスを再構築して、親友である Interop Marshaller の助けを借りて渡すことができるかどうかを調べてみてください。Delphi の文字列型でさえ .NET の文字列型とは異なることに注意してください。マーシャラーに何をすべきかを伝えずに渡すと、マーシャラーは文字配列として渡す可能性が高くなります。

それ以外は、Delphi DLL を変更することをお勧めします。非 Delphi クライアントが使用する DLL で Delphi 固有のものを公開することは、決して良いことではありません。パラメータを PChar の配列にすれば問題ありません。

于 2008-09-30T09:07:14.110 に答える
2

これがあなたの DLL なら、代わりに文字列の配列を受け入れるように関数を書き直します。クラスを DLL パラメータとして渡すことは避けてください。

または、何らかの理由で本当にTStringList を使用したい場合は、Delphi の VCL.Net を任意の .Net 言語から使用できます。

TIniFile を使用した古い例: http://cc.codegear.com/Item/22691

この例では、Delphi 2005 で .Net 1.1 を使用しています。Delphi 2006 および 2007 は .Net 2.0 をサポートしています。

于 2008-09-30T10:03:36.547 に答える
1

あなたが DLL を制御せず、彼らがそれを変更できない、または変更しない場合は、いつでも別の DLL に独自の Delphi ラッパーを記述し、言語間でより使いやすいパラメータを使用できます。

DLL 関数のパラメーターとしてクラスを持つことは、実際には悪い形式です。

于 2008-09-30T10:12:40.100 に答える
0

Hemant Jangid が言ったように、コードを .NET dll としてコンパイルし、C# プロジェクトでそのアセンブリを参照することで、これを簡単に実行できるはずです。

もちろん、これを実行できるのは、使用している Delphi のバージョンに Delphi.NET が含まれている場合のみです。

于 2008-09-30T09:48:34.493 に答える
0

私は c# についてあまり知りませんが、コンテキスト間で文字列リストを転送するために使用する手法は、.text プロパティを使用してリストを表す文字列を取得し、そのプロパティを「反対側」に割り当てることです。

通常、完全に吹き飛ばされたオブジェクトである壁を越えて文字列を取得する方が簡単です。

于 2008-10-01T03:45:25.637 に答える
0

Delphi と C# の使い方がよくわかりません。C# から呼び出したい Win32 DLL を作成したようです。もちろん、これには PInvoke を使用する必要があります。

VCL の完全な移植が可能であるため、ソース コードを使用して .NET DLL を作成することをお勧めします。ご要望があれば、さらに詳しく説明します....

于 2008-09-30T09:12:25.780 に答える
0

理論的には、厳密に型指定されたオブジェクト参照の代わりにポインターを使用する (C# IntPtr 型としてキャストする) ことによって、このようなことを行うことができます (または、安全でないブロックを宣言する必要がないように、他の型でラップする可能性があります)。これ: Delphi ランタイムは、オブジェクトのメモリを割り当ておよび割り当て解除するためのメカニズムである必要があります。そのためには、TStringList クラスのコンストラクタとデストラクタを呼び出す Delphi でコンパイルされた DLL 内の関数を宣言する必要があります。Delphi DLL が ShareMem ユニットを使用していることを確認し、参照カウントのインクリメントとデクリメントを担当する必要があります。 Delphi AnsiString に対して、DLL を出る前と入った後に、できれば Delphi DLL からエクスポートされた関数としても。

つまり、同じプロセスで 2 つのメモリ マネージャー (.NET CLR と Delphi のアロケーター) を使いこなさなければならず、手動でメモリを管理し、Delphi のメモリ マネージャーとランタイム「だます」必要があるため、これは大変な作業です。このセットアップに縛られている特定の理由はありますか? より高いレベルで解決しようとしている問題について説明していただけますか?

于 2008-09-30T09:29:24.367 に答える