passing c# object as paramater to managed c++ method

  • Thread starter Thread starter lolomgwtf
  • Start date Start date
L

lolomgwtf

I have a managed C++ method that wraps unmanaged code and creates a
managed object holding data retrieved form an unmanged one. I want
create an instance of this managed class in C#, pass it to this method
and have it set the instance to hold the right data.
From what I've read it seems I should be able to pass C# objects to
managed C++ methods and it should just work; however, when I try it, my
C# instance comes out null. If I step into the C++ method, the
debugger says the parameter is out of scope, but it doesn't throw an
exception when the parameter is referred to in the code -- I assume
this is a debugger problem. But I still don't understand why it
doesn't come out correctly set.

Sorry if this question is unclear. Here's my code, hopefully it will
be more illuminating:

// C# code
public int GetLevel1()
{
// create the managed object in C#
BWCMsgLevel1 msg = null;
// if I instantiate it, then I can set the individual fields
// in the C++ code (see note below)
// BWCMsgLevel1 msg = new BWCMsgLevel1();

// call the managed C++ code, passing the managed object as a
parameter
int result = _DataConnection.GetLevel1(m_Symbol, msg);
return result;
}

// managed C++ code
BOOL Wrapper::GetLevel1(String* sSymbol, BWCMsgLevel1*
pMsgLevel1Managed)
{
// put the String into an LPCTSTR
LPCTSTR lpctSymbol;
const char * c = (const
char*)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(sSymbol)).ToPointer();
std::string str = c;

System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr((void*)c));
lpctSymbol = str.c_str();

// create a local instance of the managed object
BWCMsgLevel1* pTest;

// create a local instance of the unmanaged object
CMsgLevel1* pMsgLevel1 = new CMsgLevel1();

// call unmanaged code to fill msgLevel1 with correct data
int nResult = m_pCStockCache->GetLevel1(lpctSymbol, pMsgLevel1, 0, 0);

if(nResult != 0)
{
// if successful getting data out of cache, put data into a
BWCMsgLevel1 object

// create a managed array of bytes
byte arr __gc[] = new byte __gc[pMsgLevel1->GetSize()];

// copy bytes from unmanaged msgLevel1 to managed arr
Marshal::Copy(msgLevel1, arr, 0, pMsgLevel1->GetSize());

// set pTest to an instance of the managed class
// at this point, I can see pTest and check its members and they are
all set correctly
pTest = new BWCMsgLevel1(arr, true);

// set parameter pMsgLevel1Managed equal to pTest
pMsgLevel1Managed = pTest;

// copy fields from unmanaged c++ level1 object to managed .NET
level1 object.
// This code works if pMsgLevel1Managed isn't null, but I would
prefer
// not to have to write code to copy each field because there are
going to be
// many, many more fields.
// The debugger still says pMsgLevel1Managed is out of scope, but I
can
// step through these lines without an error, and when I inspect the
object
// in C# the fields are set correctly.
//pMsgLevel1Managed->m_bDecimal = pMsgLevel1->m_bDecimal;
//pMsgLevel1Managed->m_cAskMC = pMsgLevel1->m_cAskMC;
//pMsgLevel1Managed->m_cBidMC = pMsgLevel1->m_cBidMC;
}

return nResult;
}

BWCMsgLevel1 is defined in a C# library that both this C# project and
the managed C++ project can see.
I'm not a C++ programmer so maybe I'm missing something. If there is a
better place to post this, please let me know. Thanks for your help.
 
The solution was given to me in
microsoft.public.dotnet.languages.csharp. It's to use an additional
level of indirection when passing the parameter, ie, BWCMsgLevel1**.
 
Back
Top