passing an array of structs from c# to C++ using com callable wrapper

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Consider the code below that is meant to be accessed by C++ using com<br/>
<br/>
namespace MarshalLib<br/>
{<br/>
//define an interface for account services<br/>
[ComVisible(true)]<br/>
[Guid("39B8A693-79BB-4638-92DE-245A88720953")]<br/>
public interface IAccountStructLookup<br/>
{<br/>
AccountStruct RetrieveAccount(int acctId);<br/>
void UpdateBalance(ref AccountStruct account);<br/>
Alias[] GetRef();<br/>
}<br/>
<br/>
//Implement an account struct<br/>
[ComVisible(true)]<br/>
[Guid("DB48C5B6-9646-491A-B030-C0CADCFC03E0")]<br/>
public struct AccountStruct<br/>
{<br/>
public int AccountId;<br/>
[MarshalAs(UnmanagedType.BStr)]<br/>
public string AccountName;<br/>
[MarshalAs(UnmanagedType.Currency)]<br/>
public decimal Balance;<br/>
<br/>
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]<br/>
//[MarshalAs(UnmanagedType.SafeArray)]<br/>
//public Alias[] Aliases;<br/>
}<br/>
<br/>
[ComVisible(true)]<br/>
[Guid("9829CAB3-4020-47EA-BE72-86EC7CFFAE1D")]<br/>
public struct Alias<br/>
{<br/>
public string Name;<br/>
}<br/>
//implement a class to provide account services<br/>
//using an AccountStruct<br/>
[ComVisible(true)]<br/>
[Guid("CEFE5CAA-5C7E-464F-8020-E0FC78180D9B")]<br/>
[ClassInterface(ClassInterfaceType.None)]<br/>
public class DniNetStructsObj : IAccountStructLookup<br/>
{<br/>
public AccountStruct RetrieveAccount(int acctId)<br/>
{<br/>
AccountStruct result = new AccountStruct();<br/>
if (acctId == 123)<br/>
{<br/>
result.AccountId = acctId;<br/>
result.AccountName = "myAccount";<br/>
result.Balance = 1009.95M;<br/>
//result.Aliases = new Alias[5];<br/>
//result.Aliases[0].Name = "1";<br/>
//result.Aliases[1].Name = "2";<br/>
//result.Aliases[2].Name = "3";<br/>
//result.Aliases[3].Name = "4";<br/>
//result.Aliases[4].Name = "5";<br/>
<br/>
}<br/>
return result;<br/>
}<br/>
<br/>
public void UpdateBalance(ref AccountStruct account)<br/>
{<br/>
//update the balance<br/>
account.Balance += 500.00M;<br/>
}<br/>
public Alias[] GetRef( )<br/>
{<br/>
Alias[] al= new Alias[2];<br/>
al[0].Name = "1";<br/>
al[1].Name = "2";<br/>
return al;<br/>
}<br/>
<br/>
<br/>
}<br/>
<br/>
And the C++ side of things<br/>
<br/>
<br/>
<br/>
#include "stdafx.h"<br/>
#include "ConsoleApplication1.h"<br/>
#import "D:Source CodeMarshalLibMarshalLibbinDebugMarshalLib.tlb" raw_interface_only<br/>
<br/>
#ifdef _DEBUG<br/>
#define new DEBUG_NEW<br/>
#endif<br/>
<br/>
<br/>
// The one and only application object<br/>
<br/>
CWinApp theApp;<br/>
<br/>
using namespace std;<br/>
using namespace MarshalLib;<br/>
<br/>
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])<br/>
{<br/>
<span style="white-space:pre int nRetCode = 0;<br/>
<br/>
<span style="white-space:pre HMODULE hModule = ::GetModuleHandle(NULL);<br/>
<br/>
<span style="white-space:pre if (hModule != NULL)<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre // initialize MFC and print and error on failure<br/>
<span style="white-space:pre if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre // TODO: change error code to suit your needs<br/>
<span style="white-space:pre _tprintf(_T("Fatal Error: MFC initialization failedn"));<br/>
<span style="white-space:pre nRetCode = 1;<br/>
<span style="white-space:pre }<br/>
<span style="white-space:pre else<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre try<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre CoInitialize(NULL);<br/>
<span style="white-space:pre IAccountStructLookupPtr api(__uuidof(DniNetStructsObj));<br/>
<span style="white-space:pre api->GetRef();<br/>
<span style="white-space:pre CoUninitialize();<br/>
<span style="white-space:pre }<br/>
<span style="white-space:pre catch (...)<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre }<br/>
<br/>
<span style="white-space:pre }<br/>
<span style="white-space:pre }<br/>
<span style="white-space:pre else<br/>
<span style="white-space:pre {<br/>
<span style="white-space:pre // TODO: change error code to suit your needs<br/>
<span style="white-space:pre _tprintf(_T("Fatal Error: GetModuleHandle failedn"));<br/>
<span style="white-space:pre nRetCode = 1;<br/>
<span style="white-space:pre }<br/>
<br/>
<span style="white-space:pre return nRetCode;<br/>
}<br/>
<br/>
I get an error when I call api-GetRef() to get an array of structs. Please help me return an array of structs from c# and use it in c++.<br/>
<br/>
thanks in advance.

View the full article
 
Back
Top