這很簡單,嘗試使用自定義編組(特別是如果你想使用char **指針)。
我發現你沒有得到「Memory ass dumb」字符串,因爲doRequest(char *,char **)的一些不正確的實現,以及分配給結果的處理不當;
首先,如果您在非託管進程中分配內存並將其傳遞給託管進程,則需要聲明一些機制來釋放非託管內存。託管GC不知道任何關於這個內存的信息,這將會丟失。其次,您需要爲結果分配內存,並將它們傳遞給非託管進程,因爲原始內存位置可以隨時重寫。
最後,你得到只是剛剛因爲你不是爲結果分配的內存,有效地只傳遞內存指針到第一輸出字符的存儲位置輸入的第一characted,說&數組[0]
這裏是競爭代碼(MS VC++/MS C#),修復所有的問題:
lib.cpp:
#include "stdafx.h"
#include "lib.h"
using namespace std;
int func1(char* input, char** output)
{
stringstream xmlInputStream, xmlOutputStream;
xmlInputStream << string(input);
int returnCode = doRequest(&xmlInputStream, &xmlOutputStream);
string xmlOutputString = xmlOutputStream.str();
//*output=const_cast<char *> (xmlOutputString.c_str());
long length = sizeof(char) * xmlOutputString.length();
char* src = const_cast<char *>(xmlOutputString.c_str());
char* dst = (char*)malloc(length+1);
memcpy_s(dst, length, src, length);
dst[length]=0; // 0 byte always ends up given ANSI string
*output = dst;
//cout << xmlOutputString;
return returnCode;
}
int func1_cleanup(char* memptr)
{
free(memptr);
return 0;
}
int doRequest(stringstream* xmlInputStream, stringstream* xmlOutputStream)
{
*xmlOutputStream << "Memory ass dumb";
return 0;
}
的Program.cs:
using System;
using System.Runtime.InteropServices;
namespace test
{
class Program
{
[DllImport("lib.dll", EntryPoint = "func1", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern unsafe int func1(char* input, char** data);
[DllImport("lib.dll", EntryPoint = "func1_cleanup", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern unsafe int func1_cleanup(char* data);
static void Main(string[] args)
{
string input = "Hello, World!";
string output;
int result = func1(input, out output);
}
private const int S_OK = 0;
public static int func1(string input, out string output)
{
unsafe
{
output = null;
int result = -1;
fixed (char* parray1 = &input.ToCharArray()[0])
{
//
// if you allocating memory in a managed process, you can use this
//
//char[] array = new char[0xffffff];
//fixed(char* parray = &array[0])
{
//
// if you allocating memory in unmanaged process do not forget to cleanup the prevously allocated resources
//
char* array = (char*)0;
char** parray2 = &array;
result = func1(parray1, parray2);
if (result == S_OK)
{
//
// if your C++ code returns the ANSI string, you can skip this extraction code block (it can be useful in Unicode, UTF-8, UTF-7, UTF-32, all C# supported encodings)
//
//byte* self = (byte*)*((int*)parray2);
//byte* ptr = self;
//List<byte> bytes = new List<byte>();
//do
//{
// bytes.Add(*ptr++);
//}
//while (*ptr != (byte)0);
//output = Encoding.ASCII.GetString(bytes.ToArray());
output = Marshal.PtrToStringAnsi(new IntPtr(*parray2));
}
func1_cleanup(array);
}
}
return result;
}
}
}
}
你在做什麼func1 w.r.t str2? – 2011-01-24 06:40:52
實際上,在func1中創建另一個char *並將其分配給str2。而這需要從c#程序中讀取......並且我不太熟悉c#。 – user186246 2011-01-24 06:43:34
@ user186246:你最終得到一個地址來查找c_str(),所以你可以自由使用我的方法,創建ByteArray結構並聲明2個參數爲ByteArray * char,那麼你可以得到一個指向該數據的apointer作爲ByteArray .ptr內存指針,並從內存中提取數據 – 2011-01-24 07:30:27