how to exchange a structure between c++/cli and c, c++

L

lightdoll

hello everyone.



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.
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.

static void NotifyToC(System::Object ^sender, Dictionary<int, _CRequested^>
^requested)
{
int nLength = requestedIndex->Count;
array<exchagned *>^ arrIndex = gcnew array<exchagned; *>(nLength);
int nCount = 0;
_CRequested^ requested;
for each(KeyValuePair<int, _CRequested^>^ pair in requested)
{
arrIndex[nCount] = new exchagned();
arrIndex[nCount]->m_nIndex = pair->Key;
requestedItem =(_CRequested^) pair->Value;
arrIndex[nCount]->m_fValue =requestedItem->m_fValue;
nCount++;
}
pin_ptr<exchagned*> p1 = &arrIndex[0]; --

|-> here is my problem.
// gCallBackofExchanged(nCount, arrIndex);--
}

so how can i solve this problem.
 
G

Giovanni Dicanio

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

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 <vector> to 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top