簡體   English   中英

通過P / Ivoke在C#中傳遞一個Struct指針(帶有char指針)

[英]Passing a Struct pointer (with char pointers in body) in C# via P/Ivoke

我在C中有一個.DLL文件。該DLL中所有函數所需的主要結構具有以下形式。

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

其中一個功能就是如下:

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

上面的所有char指針都是Input參數。

我在WinCE6 / 7設備上使用C#和.NET CF 3.5。

我嘗試使用一個類,然后將指針傳遞給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#代碼有什么問題?

我嘗試的另一件事是使用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))
    {
    }
}

在上面的例子中,在調試中,我可以檢查結構內部的指針是否未被填充,在調試視圖中,我可以看到無效引用。 無法取消引用指針消息。 其余功能因此而失敗。

在上述場景中使用Platform Invoke和Marshalling的正確方法是什么。 我試過在Google上搜索和Stack溢出。 沒找到與我類似的用例。

我相信您使用IntPtr作為char *並使用“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);

問題在於編碼。 .NET CF 3.5始終使用Unicode編碼。 我有DLL中的函數,期望字符指向ASCII中的字符串而不是Unicode。

我是這樣做的。

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])

我仍然有一些問題,使其他一些功能工作,但兩個主要功能已開始工作。

以下兩個帖子幫了很多忙。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM