Вопрос

У меня есть старая библиотека C с функцией, которая принимает значение void**:

oldFunction(void** pStuff);

Я пытаюсь вызвать эту функцию из управляемого C ++ (m_pStuff является членом родительского класса ref типа void *):

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

Это выдает мне следующую ошибку из Visual Studio:

ошибка C2440:'static_cast' (статическая передача) :не удается преобразовать из 'cli::interior_ptr' в 'void **'

Я предполагаю, что компилятор преобразует указатель на член void * в cli::interior_ptr за моей спиной.

Есть какие-нибудь советы о том, как это сделать?

Это было полезно?

Решение

Редактировать:Исправленный ответ, смотрите ниже.

На самом деле вам нужно знать, что oldFunction собирается делать с pStuff.Если pStuff является указателем на какие-то неуправляемые данные, вы можете попробовать обернуть определение m_pStuff с помощью:

#pragma unmanaged

void* m_pStuff

#pragma managed

Это сделает указатель неуправляемым, который затем может быть передан в неуправляемые функции.Конечно, вы не сможете напрямую назначить какие-либо управляемые объекты этому указателю.

Принципиально неуправляемые и управляемые указатели - это не одно и то же и не могут быть преобразованы без какого-либо связующего кода, который копирует базовые данные.В основном управляемые указатели указывают на управляемую кучу, и поскольку это собранный мусор, фактический адрес памяти, на который они указывают, может меняться со временем.Неуправляемые указатели не изменяют адрес памяти без того, чтобы вы явно этого не сделали.

Кроме того, вы не можете определить неуправляемый / управляемый внутри определения класса.Но этот тестовый код, кажется, работает просто отлично:

// 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;
}

Здесь я сначала копирую указатель из управляемого объекта, а затем передаю его oldFunction.Затем я копирую результат (вероятно, обновленный oldFunction) обратно в управляемый объект.Поскольку управляемый объект находится в управляемой куче, компилятор не позволит вам передать ссылку на указатель, содержащийся в этом объекте, поскольку он может переместиться при запуске сборщика мусора.

Другие советы

Спасибо за совет, указатель на абстрактную структуру в стиле C, которая, я думаю, если я оставлю эту структуру открытой для управляемого кода, это вызовет дополнительную боль из-за отсутствия определенной структуры.Итак, что я думаю сделать, так это обернуть библиотеку C в C ++, а затем обернуть оболочку C ++ управляемым C ++, что предотвратит раскрытие этих структур C для управляемого кода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top