views:

2403

answers:

2

I have an old C library with a function that takes a void**:

oldFunction(void** pStuff);

I'm trying to call this function from managed C++ (m_pStuff is a member of the parent ref class of type void*):

oldFunction( static_cast<sqlite3**>(  &m_pStuff ) );

This gives me the following error from Visual Studio:

error C2440: 'static_cast' : cannot convert from 'cli::interior_ptr' to 'void **'

Any advice on how to resolve this, I'm guessing the compiler is converting the void* member pointer to a cli::interior_ptr behind my back.

+1  A: 

EDIT: Fixed answer, see below.

Really you need to know what oldFunction is going to be doing with pStuff. If pStuff is a pointer to some unmanaged data you can try wrapping the definition of m_pStuff with:

#pragma unmanaged

void* m_pStuff

#pragma managed

This will make the pointer unmanaged which can then be passed into unmanaged functions. Of course you will not be able to assign any managed objects to this pointer directly.

Fundamentally unmanaged and managed pointers are not the same and can't be converted without some sort of glue code that copies the underlying data. Basically managed pointers point to the managed heap and since this is garbage collected the actual memory address they point to can change over time. Unmanaged pointers do not change the memory address without you explicitly doing so.

Scratch that, you can't define unmanaged / managed inside a class definition. But this test code seems to work just fine:

// TestSol.cpp : main project file.

#include "stdafx.h"

using namespace System;

#pragma unmanaged

void oldFunction(void** pStuff)
{
    return;
}

#pragma managed

ref class Test
{
public:
    void* m_test;

};

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Hello World");

    Test^ test = gcnew Test();
    void* pStuff = test->m_test;
    oldFunction(&pStuff);
    test->m_test = pStuff;

    return 0;
}

Here I copy the pointer out of the managed object first and then pass that in by to the oldFunction. Then I copy the result (probably updated by oldFunction) back into the managed object. Since the managed object is on the managed heap, the compiler won't let you pass a reference to the pointer contained in that object as it may move when the garbage collector runs.

Ben Childs
A: 

Thanks for the advice, the pointer is to an C style abstract structure which I think if I leave that structure exposed to the managed code is going to cause further pain due to its lack of defined structure. So what I think I will do is wrap the C library in C++ and then wrap the C++ wrapper with managed C++, which will prevent exposing those C structures to managed code.

Danielb