"lightdoll" <dj******@naver.comha scritto nel messaggio
news:97**********************************@microsof t.com...
i have made a dll of c++/cli, then i want to exchange structure between
c++/cli and c.
this is the structure
typedef struct tagExchange
{
int m_nIndex;
float m_fValue;
} exchagned;
first , c will use the dll made by c++/cli.
If C must use the DLL made by C++/CLI, this DLL must have a *pure C*
interface (i.e. use extern "C", do not pass classes at interface boundaries,
do not use function overloads, etc.).
then c will pass a function pointer to c++/cli like callback function.
because i want to use the callback like event.
typedef void (*EXCHANGED)(int nCount, exchagned stIndex[]);// callback
function.
IMHO, this naming convention is not very good...
I would name the structure as EXCHANGED (instead of lower-case 'exchanged'),
and the call back with something different and more readable, e.g.
EXCHANGED_CALLBACK.
typedef struct tagExchange
{
int m_nIndex;
float m_fValue;
} EXCHANGED;
Moreover, I would remove the m_ prefix which is spurious in that context (it
does have sense in C++ classes, not in C structures like above).
So, the final version should be:
<code>
// C guard
#ifdef __cplusplus
extern "C" {
#endif
typedef struct tagExchange
{
int nIndex;
float fValue;
} EXCHANGED, * PEXCHANGED;
// Call-back
typedef void (*EXCHANGED_CALLBACK)(int /* nCount */, PEXCHANGED /* stIndex
*/ );
#ifdef __cplusplus
}; // extern "C"
#endif
</code>
static void NotifyToC(System::Object ^sender, Dictionary<int,
_CRequested^>
^requested)
{
int nLength = requestedIndex->Count;
array<exchagned *>^ arrIndex = gcnew array<exchagned; *>(nLength);
|-here is my problem.
// gCallBackofExchanged(nCount, arrIndex);
I think that the problem is that you are passing a *managed* array
(allocated using gcnew in the managed heap), to a language (C) that has no
idea about managed heaps.
I'm not sure (you should test that...), but I think that you may consider
creating the array in the "normal" C/C++ heap, and try to pass pointer to
that to the C callback.
Something like this (using the new names I proposed above):
--[ I edited your code inline: ]--
<code>
static void NotifyToC(System::Object ^sender, Dictionary<int, _CRequested^>
^requested)
{
int nLength = requestedIndex->Count;
// array<exchagned *>^ arrIndex = gcnew array<exchagned; *>(nLength);
// Create array on normal heap, not managed heap, to pass to C callback
// Create a vector of nLength EXCHANGED itgems.
// You need to #include <vectorto use STL vector container.
std::vector< EXCHANGED arrIndex( nLength );
int nCount = 0;
_CRequested^ requested; // <--- initialized where?
for each(KeyValuePair<int, _CRequested^>^ pair in requested)
{
// arrIndex[nCount] = new exchagned(); <- REMOVE THAT
// You can use dot notation here:
arrIndex[nCount].nIndex = pair->Key;
requestedItem =(_CRequested^) pair->Value;
arrIndex[nCount].fValue =requestedItem->m_fValue;
// If you have some problems for buffer overruns,
// you may use arrIndex.at() instead of operator[];
// In fact, std::vector::at() is bounds-checked.
nCount++;
}
// Call C call-back
gCallBackofExchanged( nCount, &(arrIndex[0]) );
// No need to remove EXCHANGED array:
// std::vector destructor does that automatically.
}
</code>
HTH,
Giovanni