Прямой доступ к памяти библиотеки 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, так как это действительно хорошо, как это есть.



Любая помощь или разъяснение высоко ценится, большое спасибо, приветствую

603   1  

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

    Ничего не найдено.