Прямой доступ к памяти библиотеки DLL C++ в C#
Я искал stackoverflow для этой проблемы, но не нашел этого точного. В частности, я нашел массу вопросов, касающихся извлечения ссылок на строки C++ (char**), когда сторона C# управляет памятью, но не наоборот.
Ситуация выглядит следующим образом. У меня есть DLL (написанная на VC++ 2012), которую я написал сам. Он загружает и анализирует данные из файлов, а затем позволяет любому, кто использует DLL доступ к этим данным (фактический прямой доступ к памяти по соображениям производительности) в нескольких направлениях. Любая программа В C++, использующая эту DLL, очевидно, не имеет проблем с этим. C# , как кажется, делает...
Немного контекста:
Библиотека DLL предоставляет экспортированные функции, принимающие параметры char** (массивы параметров char*), элементы которых устанавливаются в ячейки памяти библиотеки DLL и затем обрабатываются пользователем библиотеки DLL после вызова.
Пример может выглядеть так (примерная реализация):
int myFunction(char* dataArray[], int row)
{
for (int i= 0; i < _something; ++i)
{
dataArray[i] = _some_char_ptr
}
}
И это то, что реализация вызываемого может быть выглядит как в C++:
char** data = new char*[__num_fields];
myFunction(data, __some_row);
for (int i= 0; i < __something; ++i)
{
cout << data[i] << endl;
}
Особенность - таким образом, отличающаяся от всех вопросов, которые я нашел-заключается в том, что вызываемый объект выделяет список символов*, которые после вызова указывают на места памяти, выделенные самой DLL.
Теперь, должен сказать, Я использую C# только потому, что вы можете получить довольно простые GUIs в notime. Инструмент c# GUI, над которым я работаю, предназначен для проверки целостности данных, загружаемых DLL. Я совсем не разбираюсь в C#. То, что я пробовал до сих пор, не увенчалось успехом, и я знаю, что это может быть не будет никакого решения для этой проблемы из-за того, что C# не имеет каких-либо понятий указателей. Аналогичные проблемы я обнаружил в Java при использовании JNA для загрузки DLL, что привело к тому, что я больше не использую Java для таких целей тестирования.
Теперь немного C# вещей, которые я пробовал, ВКЛ. контекст:
public static class DLLTest
{
// delegate object for the function:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int MyFunction_Type(out string[] dataArray, int row);
public static MyFunction_Type MyFunction { get; private set; }
public static void Load()
{
IntPtr dllAddress = DllUtilities.LoadLibrary(@"__dll_path");
IntPtr procAddress = DllUtilities.GetProcAddress(dllAddress, "myFunction");
MyFunction = (MyFunction_Type)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(MyFunction_Type));
}
}
Затем я вызываю функцию следующим образом:
string[] data = new string[__num_fields];
DLLTest.MyFunction(out data, __row)
Код, подобный этому, используя такие вещи, как обычные строки, целые числа, булевы, что угодно, работает как очарование. Просто эти строковые массивы не дают мне покоя. :- )
Примечание: Я не могу изменить способ работы DLL, потому что я написал это для моего босса, и он прекрасно использует его как в программах C++, так и в Delphi. Он работает хорошо, и мы не собираемся ничего менять в самой DLL, так как это действительно хорошо, как это есть.
Любая помощь или разъяснение высоко ценится, большое спасибо, приветствую
1 ответ:
out string[] dataArray- неверный перевод для параметра
char**. Это должно быть:IntPtr[] dataArrayВызывающий код C# затем выделяет массив перед вызовом функции. Так же, как и код C++.
IntPtr[] data = new IntPtr[__num_fields]; int retval = DLLTest.MyFunction(data, __row);Затем вы можете получить доступ к памяти вашего сердца, используя класс
Marshalдля чтения неуправляемой памяти за указателямиIntPtr.Соглашение о вызовах выглядит немного странно. Как написано, функция C++ - это
cdecl. Как говорит Ханс, также должен быть какой-то механизм для DLL чтобы узнать, сколько времени прошло в массиве.
Comments