1

作成したcコードから文字列を取得するのに問題があります。

まず、一般的に実現されていない背景情報:TAPIAPIからTAPITSPのユーザーが読み取り可能な文字列を受け取りたいのですが。ドライバー名を保存された文字列に一致させることに依存する半実行可能なTAPIソリューションを実装しましたが、お客様の1人が他の方法で動作することを拒否する(Alcatel)PBXを持っているため、代わりに永続的な回線IDで動作するようにこれを変更したいと思います。

Cでは、ヘッダーファイルで関数を次のように定義します。

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName);

関数は次のように記述されます。

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName)
{
    //tapi code here...

    //copy the string to DeviceName
    wcscpy(DeviceName, (wchar_t*)((char *)devCaps + devCaps->dwLineNameOffset));
}

上で述べたように、これは最終的には何か便利なことをしますが、今のところ、abcがwchar_t * / StringBuilderに配置されていて、C#でそれを見ることができれば幸いです。

C#では、関数を次のように定義します。

    [DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
    static extern void GetDeviceName(long DeviceId, StringBuilder DeviceName);

文字列は不変であり、DeviceNameをCで設定したいのでDeviceNameをStringBuilderとして定義します(これはMSによって推奨されています)。void私はまた、それが何かにも影響を与えるという細い希望に基づいてリターンタイプを設定しました(部分的な疑似科学的説明については、この半有用なモノの記事を参照してください)。

そしてそれをそう呼んでください:

StringBuilder name = new StringBuilder();
name.EnsureCapacity(100);
long n = 0;
GetDeviceName(n, name);

実行中のプロセスにデバッガーを接続し、ブレークポイントを設定すると、Cコードで、StringBuilderが何らかの形で変質し、アンマネージコードにnullポインターとして提供されていることに気付きます。

その後、AccessViolationExceptionがC#でスローされます。

何が問題なのですか?

longパラメータを削除すると役立ちます。CのDeviceNameパラメーターに「abc」を追加できます。ただし、その長い変数が必要です。その長いパラメータをそこに置くことによってクラッシュを強制するために、私は間違っているか動揺しているのですか?

4

3 に答える 3

2

しかし、その長い変数が欲しい

次に、C でパラメーターを として定義する必要がありますlong long。Lucero が指摘したように、C++ の long は 32 ビットですが、C# の long は 64 ビットです。そのため、C 関数が 32 ビット値を想定している場所に 64 ビット値を渡すと、関数は余分な 32 ビットを 2 番目のパラメーターとして読み取るため、明らかにバッファーのアドレスが間違ってしまいます...

于 2010-01-08T14:31:09.037 に答える
1

C ++longは32ビット、C#longは64ビットですね。intしたがって、最初のパラメータにはを使用する必要があります。

于 2010-01-08T11:00:06.077 に答える
1

32 ビット プラットフォームlongでは、.NET では 8 バイト (64 ビット) 幅、ネイティブ コードでは 4 バイト (32 ビット) 幅です。P/Invoke メソッドを次のように変更する必要があります。

[DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
static extern void GetDeviceName(int DeviceId, StringBuilder DeviceName);

このように、C#intと Clongは 32 ビット プラットフォームで同じ幅になります。

于 2010-01-08T14:31:06.993 に答える