Я экспериментировал с этим некоторое время назад, но, к сожалению, забыл, как все это совмещалось ... для моей цели это оказалось ужасно медленным, поэтому я отключил C # и вернулся ко всему C ++. Когда вы говорите, что вы в первую очередь разработчик C #, я надеюсь, что вы понимаете указатели, потому что если вы этого не сделаете, нет способа быть мягким.
Передача массивов в основном сводилась к использованию семейства функций CoTaskMemAlloc на стороне C ++ (http://msdn.microsoft.com/en-us/library/ms692727(VS.85).aspx) и класса Marshal на стороне C # (http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.aspx - у которого есть такие методы, как AllocCoTaskMem). Для C # Я закончил с классом полезности:
public class serviceUtils
{
unsafe public long stringToCoTaskPtr( ref str thestring )
{
return (long)Marshal.StringToCoTaskMemAnsi(thestring.theString).ToPointer();//TODO : what errors occur from here? handle them
}
unsafe public long bytesToCoTaskPtr( ref bytes thebytes, ref short byteCnt)
{
byteCnt = (short)thebytes.theArray.Length;
IntPtr tmpptr = new IntPtr();
tmpptr = Marshal.AllocCoTaskMem(byteCnt);
Marshal.Copy(thebytes.theArray, 0, tmpptr, byteCnt);
return (long)tmpptr.ToPointer();
}
public void freeCoTaskMemPtr(long ptr)
{
Marshal.FreeCoTaskMem(new IntPtr(ptr));//TODO : errors from here?
}
public string coTaskPtrToString(long theptr)
{
return Marshal.PtrToStringAnsi(new IntPtr(theptr));
}
public byte[] coTaskPtrToBytes(long theptr, short thelen)
{
byte[] tmpbytes = new byte[thelen];
Marshal.Copy(new IntPtr(theptr), tmpbytes, 0, thelen);
return tmpbytes;
}
}
Просто, чтобы добавить к вам еще немного кода:
это с ++
#import "..\COMClient\bin\Debug\COMClient.tlb" named_guids raw_interfaces_only
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL); //Initialize all COM Components
COMClient::IComCalculatorPtr pCalc;
// CreateInstance parameters
HRESULT hRes = pCalc.CreateInstance(COMClient::CLSID_ComCalculator);
if (hRes == S_OK) {
long size = 5;
LPVOID ptr = CoTaskMemAlloc( size );
if( ptr != NULL )
{
memcpy( ptr, "12345", size );
short ans = 0;
pCalc->changeBytes( (__int64*)&ptr, &size, &ans );
CoTaskMemFree(ptr);
}
}
CoUninitialize (); //DeInitialize all COM Components
return 0;
}
назвал это c #
public short changeBytes(ref long ptr, ref int arraysize)
{
try
{
IntPtr interopPtr = new IntPtr(ptr);
testservice.ByteArray bytes = new testservice.ByteArray();
byte[] somebytes = new byte[arraysize];
Marshal.Copy(interopPtr, somebytes, 0, arraysize);
bytes.theArray = somebytes;
CalculatorClient client = generateClient();
client.takeArray(ref bytes);
client.Close();
if (arraysize < bytes.theArray.Length)
{
interopPtr = Marshal.ReAllocCoTaskMem(interopPtr, bytes.theArray.Length);//TODO : throws an exception if fails... deal with it
}
Marshal.Copy(bytes.theArray, 0, interopPtr, bytes.theArray.Length);
ptr = interopPtr.ToInt64();
arraysize = bytes.theArray.Length;
//TODO : do we need to free IntPtr? check all code for memory leaks... check for successful allocation
}
catch(Exception e)
{
return 3;
}
return 2;
}
Извините, но у меня нет времени, чтобы разобраться со всем этим и объяснить это должным образом, надеюсь, это даст вам указатели в правильном направлении, по крайней мере, некоторые вещи для Google. Удачи
PS: у меня есть вся информация, чтобы написать этот материал из сети, так что он там.