4

C の .DLL ファイルがあります。その DLL 内のすべての関数に必要な主要な構造は、次の形式です。

typedef struct
{
    char *snsAccessID;      
    char *snsSecretKey;     
    char *snsPath;          
    char *snsTopicName;     
    char *snsTopicAmazonResourceName; 
    char *snsDisplayName;   
    char *snsOwnerId;       
} snsTopic, *HSNS;

たとえば、関数の1つは次のとおりです。

BOOL SnsOpenTopic(char *accessID, char *secretKey, char *ownerId, char *path, char *topicName, char *displayName, HSNS *snsTopicHandle);

上記のすべての char ポインターは入力パラメーターです。

WinCE6/7 デバイスで .NET CF 3.5 で C# を使用しています。

クラスを使用してから、次のように C 関数に必要な構造体へのポインターを渡してみました。

public class HSNS
{
    public string snsAccessID;      
    public string snsSecretKey;     
    public string snsPath;          
    public string snsTopicName;     
    public string snsTopicAmazonResourceName; 
    public string snsDisplayName;   
    public string snsOwnerId;       
}

[DllImport("Cloud.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SnsOpenTopic(string accessID, string secretKey, string ownerId, string path, string topicName, string displayName, ref HSNS snsTopicHandle);

上記の C# スニペットを使用すると、NotSupportedException がスローされます。上記の C# コードの何が問題なのかわかりませんか?

私が試したもう 1 つのことは、C# でアンマネージ コードを使用することです。

unsafe public struct HSNS
{
    public char *snsAccessID;      
    public char *snsSecretKey;     
    public char *snsPath;          
    public char *snsTopicName;     
    public char *snsTopicAmazonResourceName; 
    public char *snsDisplayName;   
    public char *snsOwnerId;       
}

[DllImport("Cloud.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SnsOpenTopic(string accessID, string secretKey, string ownerId, string path, string topicName, string displayName, HSNS *snsTopicHandle);

fixed (HSNS *snsAcsTopicHandle = &snsAcsTopic)
{
    if (SnsOpenTopic(AWS_ACCOUNT_ACCESS_ID, AWS_ACCOUNT_SECRET_KEY, AWS_ACCOUNT_OWNER_ID, AWS_SNS_SINGAPORE_REGION, topicName, displayName, snsAcsTopicHandle))
    {
    }
}

上記の場合、デバッグで構造内のポインターが設定されていないことを確認でき、デバッグ ビューで無効な参照が表示されます。ポインター メッセージを逆参照できません。このため、残りの関数は失敗します。

上記のシナリオでプラットフォーム呼び出しとマーシャリングを使用する正しい方法は何ですか? Google と Stack Overflow で検索してみました。私のようなユースケースは見つかりませんでした。

4

2 に答える 2

0

char* には IntPtr を使用し、構造には "ref" を使用していると思います

[DllImport("Cloud.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SnsOpenTopic(string accessID, string secretKey, string ownerId, string path, string topicName, string displayName, ref HSNS snsTopicHandle);

[StructLayout(LayoutKind.Sequential)]
public struct HSNS
{
    public IntPtr snsAccessID;      
    public IntPtr snsSecretKey;     
    public IntPtr snsPath;          
    public IntPtr snsTopicName;     
    public IntPtr snsTopicAmazonResourceName; 
    public IntPtr snsDisplayName;   
    public IntPtr snsOwnerId;       
}

次に、構造の結果にアクセスする場合は、IntPtr を文字列にマーシャリングする必要があります。

http://msdn.microsoft.com/en-us/library/7b620dhe.aspx

System.Runtime.InteropServices.Marshal.PtrToStringAnsi(snsTopicHandler.snsPath);

またはhttp://msdn.microsoft.com/en-us/library/ewyktcaa.aspx

System.Runtime.InteropServices.Marshal.PtrToStringAuto(snsTopicHandler.snsPath);
于 2013-07-29T16:52:17.693 に答える
0

問題はエンコーディングにありました。.NET CF 3.5 は全体で Unicode エンコーディングを使用します。私が持っていたDLLの関数は、UnicodeではなくASCIIの文字列への文字ポインタを期待していました。

私はこのようにしました。

unsafe public struct HSNS
{
    public char *snsAccessID;      
    public char *snsSecretKey;     
    public char *snsPath;          
    public char *snsTopicName;     
    public char *snsTopicAmazonResourceName; 
    public char *snsDisplayName;   
    public char *snsOwnerId;       
}

[DllImport("Cloud.dll", SetLastError = true)]
public unsafe static extern Boolean SnsOpenTopic(Byte* accessID, Byte* secretKey, Byte* ownerId, Byte* path, Byte* topicName, Byte* displayName, ref HSNS snsAcsTopic);

// Sample of encoding conversion
public Byte[] topicName = Encoding.ASCII.GetBytes("CSharpACSAlert\0");

そして、以下を使用してポインターを取得し、修正します

fixed (Byte* ptrTopicName = &topicName[0])

他のいくつかの機能を機能させるにはまだ問題がありますが、2 つの主要な機能は機能し始めています。

以下の2つの投稿は非常に役立ちました。

http://www.codeproject.com/Articles/5888/An-Introduction-to-P-Invoke-and-Marshaling-on-the

http://www.codeproject.com/Articles/5890/Advanced-P-Invoke-on-the-Microsoft-NET-Compact-Fra

于 2013-07-30T13:48:49.413 に答える