Код C #:
DllTestMgr dllTest = new DllTestMgr();
GetDllTestFP(ref dllTest);
DllTestFPStruct dllFPs = (DllTestFPStruct)Marshal.PtrToStructure(dllTest.psItf, typeof(DllTestFPStruct));
VersionInfo vInfo = new VersionInfo();
dllFPs.Close(ref vInfo);
Вам не нужно выделять dllTest.psItf
, поскольку в GetDllTestFP
вы делаете:
DLLTESTC_API void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP)
{
psFP->psItf = &sFP;
}
Таким образом, вы копируете адрес из sFP
.
Обратите внимание, что в целом это плохая идея, потому что вы предоставляете "клиенту" прямой доступ к вашим данным (структура sFP
).Альтернатива состоит в том, что клиент передает память (как вы писали ранее), а затем вы делаете:
(*psFP->psItf) = sFP;
(но затем не забудьте освободить выделенную память!)
Третья альтернатива,C-сторона выделяет блок памяти через общий распределитель (тот, который может использоваться C #, поэтому здесь нет malloc
/ new
), а затем C # должен освободить его.
неправильное решение -
STRUCT_DLL_TEST_FP_STRUCT sFP2 = sFP;
psFP->psItf = &sFP2;
Время жизни sFP2
заканчивается, когда метод возвращается.psFP->psItf
теперь указывает на кусок стека, который больше не существует. не делайте этого!
Ах ... как написано @Hans Passant, в зависимости от того, кто выделяет память, GetDllTestFP
может быть ref
или out
.Если память выделена C #, то она должна быть ref
, если она не выделена (как сейчас) или выделена C ++, тогда out
в порядке, и вы сэкономите на маршалинге в одном направлении.