簡體   English   中英

使用DLL將C#StringBuilder / string傳遞給C ++ char *

[英]Passing C# StringBuilder / string to C++ char* using DLL

我一直在使用C#GUI和用於套接字連接處理的C ++代碼。 問題是將字符串傳遞給C ++ char * DLL會導致它在C ++類(?)中更改其值。

我有一個用於處理套接字的類,它有點改變以查找錯誤原因以及一些函數讓我自己進入類:

extern "C" { __declspec(dllexport)

    class mySock
    {

        int port;
        SOCKET littleSock;

        public:
            char* ipAddress;
            mySock() {};
            mySock(char* inIP, int inPort);
            ~mySock();
            int initialize();
            int sendMsg(char* Msg);
            //int addition(int a, int b);

    };
}

extern "C" { __declspec(dllexport) mySock* mySock_Create(char* IP, int prt);}
extern "C" { __declspec(dllexport) mySock* mySock_Create1(); }
extern "C" { __declspec(dllexport) int mySock_initialize(mySock* inSocket); }
extern "C" { __declspec(dllexport) int mySock_sendMsg(mySock* inSocket,char* Msg); }
extern "C" { __declspec(dllexport) void mySock_delete(mySock* inSocket); }
extern "C" { __declspec(dllexport) void CopyStr(char* str1, mySock* inSocket)
    {
        strcpy_s(str1, strlen(str1), inSocket->ipAddress);
    };
}

問題發生在使用mySock_Create的某個地方。

基本上它是:

mySock* mySock_Create(char* IP, int prt)
{
    return new mySock(IP, prt);
}

調用構造函數:

mySock::mySock(char* inIP, int inPort)
{
    ipAddress = inIP;
    port = inPort;
}

后來的ipAddress與inet_addr一起使用並連接到遠程服務器。 無論如何,上面的代碼不允許我連接到服務器,但如果我只是硬編碼這樣的IP地址:

mySock* mySock_Create(char* IP, int prt)
{
    return new mySock("192.168.1.164", prt);
}

它工作正常並連接到本地服務器。

因此,為了檢查我添加了你可以在上面的DLL頭代碼中看到的CopyStr,它應該獲取mySock對象的IP地址並將其寫入C#文本框。

如果硬編碼的IP地址確實顯示了IP地址,但是如果從C#傳遞IP地址,它只返回一個未填充的矩形符號,我甚至無法在此處粘貼。

這是用於鏈接和使用DLL的C#代碼:

[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mySock_Create(StringBuilder IP, int prt);
[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mySock_initialize(IntPtr value);
[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mySock_sendMsg(IntPtr value, string Msg);
[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mySock_delete(IntPtr value);
[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mySock_Create1();
[DllImport("G:\\socketstraning\\klikacz\\MyFirstDLLyay\\Debug\\MyFirstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void CopyStr(StringBuilder str1, IntPtr value);

private void button3_Click(object sender, EventArgs e)
{
    StringBuilder str = new StringBuilder("192.168.1.164", 50);
    IntPtr we = mySock_Create(str, 16999);
    StringBuilder str2 = new StringBuilder("255.255.255.255", 25);
    CopyStr(str2, we);
    textBox1.Text = str2.ToString();
    if (mySock_initialize(we) == -2)
         button3.Text = "Ups";

    mySock_delete(we);
}

我也嘗試使用字符串而不是StringBuilder或在導入選項中添加CharSet = CharSet.Ansi。

在這種情況下,我已經閱讀了很多將字符串傳遞給char*的問題和解決方案,但我無法理解為什么ipAddress值未正確傳遞或在其他地方更改。

希望我能夠清楚地說明問題,因為在與上述代碼作戰之后我已經非常缺乏邏輯。

主要問題在於您的C ++構造函數:

mySock::mySock(char* inIP, int inPort)
{
    ipAddress = inIP;
    port = inPort;
}

在這里,您可以復制指向字符數組的指針。 只要您需要使用ipAddress ,這就要求此指針保持有效。 從C#封送的字符串僅在p / invoke調用期間有效。

實際上,即使你只使用C ++這個類,它的設計也是行不通的。 您的類需要獲取字符串的副本而不是指針的副本。

解決方案是讓您的C ++代碼專門使用std::string 讓該類負責內存管理和復制。 僅在p / invoke互操作邊界處使用C字符串。

ipAddress更改為std::string類型,並使構造函數如下所示:

mySock::mySock(const std::string inIP, const int inPort)
{
    ipAddress = inIP;
    port = inPort;
}

您仍然需要在interop包裝函數中使用C字符串,但這可以使用從const char*std::string的隱式轉換。

mySock* mySock_Create(const char* IP, const int prt)
{
    return new mySock(IP, prt);
}

就p / invoke而言,你濫用了StringBuilderchar* 當您具有被調用者修改的調用者分配的緩沖區時,它們將配對。 對於傳入C ++代碼的string ,請使用stringconst char*

[DllImport("...", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mySock_Create(string IP, int prt);

暫無
暫無

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

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