Но как заставить его указывать на новую ячейку памяти, а не изменять значение?
Итак, я так понимаю вопрос, вы спрашиваете, как вернуть адрес переменной в нативном модуле. Делай это так:
static int i = 42;
extern "C" _declspec(dllexport) int* getPtr()
{
return &i;
}
Обратите внимание, что переменная, адрес которой возвращается, не является локальной переменной. Это не может быть адрес локальной переменной, потому что область действия локальной переменной заканчивается, когда функция возвращается.
И из С# назовите это так:
[DllImport("...", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr getPtr();
....
IntPtr ptr = getPtr();
int i = Marshal.ReadInt32(ptr);
Если вы предпочитаете возвращать указатель через параметр, сделайте это следующим образом:
static int i = 42;
extern "C" _declspec(dllexport) void getPtr(int** ptr)
{
*ptr = &i;
}
И из С#:
[DllImport("...", CallingConvention = CallingConvention.Cdecl)]
static extern void getPtr(out IntPtr ptr);
....
IntPtr ptr;
getPtr(out ptr);
int i = Marshal.ReadInt32(ptr);
Однако, сказав все это, я действительно сомневаюсь, что вы действительно хотите вернуть адрес переменной. Эта глобальная переменная не выглядит очень полезной. И альтернатива — память, выделенная кучей. Но тогда вам нужно экспортировать делокатор или выделить из общей кучи. Опять же, особого удовольствия там не будет. И боль в шее тоже для сортировки.
Гораздо более полезно выделить переменную в вызывающем коде, управляемом коде и попросить собственный код изменить значение этой переменной. Это делает управление жизненным циклом тривиальным и позволяет вам позволить маршаллеру pinvoke выполнять всю работу.
person
David Heffernan
schedule
03.01.2014
*a = 1;
(не то чтобы это не обязательно решит проблему, которую он хочет решить, конечно) Или это всегда должно было быть определеноvoid modifyVar(int& a) {...}
- person   schedule 04.01.2014