2016-07-20 3 views
0

Я пытаюсь передать указатель класса из родной DLL в CLR. Я не настолько успешна в этом. Я добираюсь до точки, в которой он возвращает указатель, используя void *, а затем преобразовывая его в ClassType * с помощью IntrPtr и ToPointer(). Но в тот момент, когда я пытаюсь получить доступ к его методам-членам, он не может получить старые значения свойств. Вместо этого я получаю 0 и некоторые случайные значения.Можно ли передавать указатели объектов между CLR и родным C++?

Я даже пытался использовать VC100 в качестве набора инструментов для CLR и native dll. Тем не менее я получаю значение «Ошибка чтения символов строки».

Я пытался использовать Google и не могу найти много информации о передаче указателей объектов из native в CLR. Я упомянул даже о step-by-step, доступном в проекте кода.

Edited добавить это:


У меня есть DLL родной, где функция, которая возвращает указатель на объект

Native.dll:

#if defined EXPORTDLL // inside DLL 
#define DLL_EXPORT __declspec(dllexport) 
#else // outside DLL 
#define DLL_EXPORT __declspec(dllimport) 
#endif 

..... 

DLL_EXPORT void* SomeMethod(uint16_t num1, const char * str1, const char * str2) 
{ 
    Obj1 obj(...); 
    ... 
    return (void*)&obj; // <- at this point it is still correct 
} 

.... 
class DLL_EXPORT Obj1{ 
.... 
const std::string var1; 
const std::string var2; 
const std::string var3; 
.... 
DLL_EXPORT strct1 memberFunction1() 
{ 
    // do something with the variables 
    // here when its called by managed code, the var1, var2, var3 shows random values and bad ptr.. 
} 
... 
} 

, а затем в управляемый код CLR I вызовите memberFunct1 с помощью указателя возврата.

[DllImport("Native.dll", EntryPoint = "[email protected]@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]", CallingConvention = CallingConvention::Cdecl)] 
IntPtr * SomeMethod(uint16_t num1, [In, MarshalAs(UnmanagedType::LPStr)]String^ str1, [In, MarshalAs(UnmanagedType::LPStr)] String^ str2); 
..... 

String^ str1 = gcnew String("1223568"); 
String^ str2 = gcnew String("1.2.3.5"); 
Obj1 *objptr = (Obj1*)(SomeMethod(1,str1, str2)).ToPointer(); 
// <- at this point the objptr properties are showing garbage 
objptr->memberFunction1(); 

Я использую этот obj1 указатель для вызова метода члена, но в методе члена значения членов показывают, как плохо PTR.


Может кто-нибудь указать мне в правильном направлении, пожалуйста?

Заранее спасибо.

Я добавил дополнительный метод в свою родную dll.

void DLL_EXPORT SomeMethod2(int i1, const char* var1, const char* var2, Obj1* retval); 

И назвал его из моего CLR проекта

[DllImport("Native.dll", EntryPoint = "[email protected]@[email protected]@@Z", CallingConvention = CallingConvention::Cdecl)] 
void SomeMethod2(int i1, [MarshalAs(UnmanagedType::LPStr)]String^ var1, [MarshalAs(UnmanagedType::LPStr)]String^ var2, Obj1* retval); 
.... 
Obj1 * testPtr3; 
SomeMethod2(1, (char*)(void*)Marshal::StringToHGlobalAnsi(str1), (char*)(void*)Marshal::StringToHGlobalAnsi(str2), testPtr3); 
SomeMethod2(1, str1, str2, testPtr3); 

Obj1 testPtr2 = Obj1(1, (char*)(void*)Marshal::StringToHGlobalAnsi(str1), (char*)(void*)Marshal::StringToHGlobalAnsi(str2)); 

Но я получаю ошибки ссылку? Я уже связал это ?? !! ??

ошибка LNK2028: неразрешенный токен (0A000356) "public: __thiscall Obj1 :: Obj1 (int, char const *, char const *)" (?? 0Obj1 @@ $$ FQAE @ HPBD0 @ Z), на который ссылается функция " int __cdecl main (void) "(? main @@ $$ HYAHXZ)

ошибка LNK2028: неразрешенный токен (0A00035B)" void __cdecl SomeMethod2 (int, char const *, char const *, class Obj1 *) "(? SomeMethod2 @@ $$ FYAXHPBD0PAVObj1 @@@ Z) ссылка в функции "INT __cdecl основной (ничтожной)" (главный @@ $$ HYAHXZ)

ошибка LNK2019: неразрешенный внешний символ «общественность: __thiscall Obj1 :: Obj1 (int, char const *, char const *) "(?? 0Obj1 @@ $$ FQAE @ HPBD0 @ Z), на который ссылается функция" int __cdecl main (void) "(? main @@ $$ HYAHXZ)

ошибка LNK2019: неразрешенный внешний символ "void __cdecl SomeMethod2 (int, char const *, char const *, класс Obj1 *)" (? SomeMethod2 @@ $$ FYAXHPBD0PAVObj1 @@@ Z), на который ссылается функция "int __cdecl main (void) "(?Основной @@ $$ HYAHXZ)

enter image description here

+0

@Martin Извините, я редактировал свое сообщение и добавил некоторые коды. – ras

+0

Это стандартное болото [ошибка оборванного указателя] (https://en.wikipedia.org/wiki/Dangling_pointer). Очень распространенная ошибка в программе на C или C++, обычно очень сложная для диагностики. Но не тогда, когда вы используете pinvoke, пространство стека, требуемое маршеллером pinvoke, гарантирует, что 'obj' будет перезаписано надежно. Вы должны сохранить его в другом месте, лучшее место почти всегда является стекю стека вызывающего. Измените тип возврата на void и добавьте параметр 'Obj1 * retval'. –

+0

@ HansPassant Я тоже попробовал. Но я все еще получаю сообщение об ошибке. Я редактировал свой пост, чтобы включить то, что вы упомянули, и добавил изображение, показывающее ссылку. – ras

ответ

1

Вы не используете C++/CLI, таким образом!

Весь пункт C++/CLI должен действовать как клей между миром .NET и родным миром.

Что вы делаете, а не является:

  • Включите ++ заголовки C для SomeMethod и class Obj1 в исходном файле C++/CLI и
  • имеют С ++/CLI сборки ссылаться на Native.dll проекту

Затем вы можете просто использовать его, как обычно, в C++ - convert any CLR types to native representation first (System :: String может быть преобразован MFC CString, если вы включили MFC):

String^ str1 = gcnew String("1223568"); 
String^ str2 = gcnew String("1.2.3.5"); 
Obj1 *objptr = SomeMethod(1, CString(str1), CString(str2)); 

А почему вы видите мусор в отладчике: Это, вероятно, потому, что вы возвращаете адрес локального объекта:

DLL_EXPORT void* SomeMethod(uint16_t num1, const char * str1, const char * str2) 
{ 
    Obj1 obj(...); 
    ... 
    return (void*)&obj; // <- at this point it is still correct 
} 

В этом случае obj будут очищены (его вызванный D'tor и его стековая память переработаны), как только вы вернетесь с SomeMethod.

  • Либо возвращает объект по значению
  • или new до объекта и возвращает указатель. (хотя это код для предотвращения утечки)
+0

Я сделал это. Я включил файл заголовка и скопировал файл Native.dll и добавил его в качестве ссылки на мой проект CLR. Я создал экземпляр, и я получаю сообщение об ошибке ??! ?? [ошибка LNK2028: неразрешенный токен (0A00041D) "public: __thiscall SomeDLLClass1 :: SomeDLLClass1 (int, char const *, char const *)" (? 0SomeDLLClass1 @@ $$ FQAE @ HPBD0 @ Z), на который ссылается функция "int __clrcall main (cli :: array ^) "] – ras

+0

Строка сущности [Obj1 testPtr2 = Obj1 (1, (char *) (void *) Маршал :: StringToHGlobalAnsi (str1), (char *) (void *) Маршал :: StringToHGlobalAnsi (str2));] – ras

+0

@ras - вы не скопируете Native.dll и добавьте его в качестве ссылки. Вы должны добавить Native.vcxproj в качестве ссылки и активировать 'Link Lib Dependencies == true'. - альтернативно, вы ссылаетесь на файл .lib' из собственного проекта, если родной проект живет в более узком решении. –

 Смежные вопросы

  • Нет связанных вопросов^_^