Отличия в методах вызова неуправляемой C ++ dll из C # - PullRequest
2 голосов
/ 16 апреля 2019

Я вызываю некоторые неуправляемые функции C (во внешней dll) из C #. У меня есть 2 разных способа сделать это, и я не уверен в разнице между 2 (кроме количества кода)

Метод № 1

[DllImport("PComm32.dll",CallingConvention=CallingConvention.StdCall, EntryPoint ="PmacSelect")]
public static extern int PmacSelect(IntPtr intPtr);

int device = PmacSelect(IntPrt.Zero);

Метод № 2

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int PmacSelect(IntPrt intptr);

[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);

public PmacSelect PmacSelectFunction;


private IntPtr pDll = LoadLibrary("PComm32");
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "PmacSelect"); //find the function in the loaded pcomm32 dll

PmacSelectFunction = (PmacSelect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,type(PmacSelect));

int device = PmacSelectFunction(IntPrt.Zero);

Оба метода работают, и вызывают функцию PmacSelect, расположенную в файле PComm32.dll. Мой вопрос: каковы функциональные различия между этими двумя методами? Метод № 1 должен опираться на Windows, управляющий DLL в фоновом режиме для меня, если это необходимо? Могут ли Windows загружать и выгружать DLL без моего ведома? Мне действительно все равно, если это происходит, если он автоматически загружается, когда я вызываю функцию в dll.

Метод # 2 DLL загружается явно, когда я вызываю LoadLibrary. Библиотека остается в памяти, пока я ее не освобожу?

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Я дам вам ответы, но вы, кажется, уже понимаете, что происходит.

Мой вопрос: каковы функциональные различия между этими двумя методами?

Между этими двумя методами нет функциональной разницы.В первом методе (который вы должны использовать, если это вообще возможно), платформа DotNet обрабатывает все для вас.Под капотом он делает именно то, что вы делаете вручную: звоните LoadLibrary, GetProcAddress, а в какой-то момент FreeLibrary.Это шаги к вызову функции в DLL.

Метод № 1 должен опираться на окна, управляющие DLL в фоновом режиме для меня, если это необходимо?Могут ли Windows загружать и выгружать dll без моего ведома?

Да, именно так, хотя я бы не сказал, что без вашего ведома.Вы говорите это делать, когда пишете [DllImport("PComm32.dll"...)].

Метод # 2. DLL загружается явно, когда я вызываю LoadLibrary.Библиотека остается в памяти до тех пор, пока я ее не освобожу?

Опять же, да, вы понимаете, что происходит.


Поскольку вы, кажется, ответили на свои вопросы, а я лишь подтвердил ваши ответы, позвольте вам объяснить, почему вы должны (почти) всегда использовать # 1:

  1. Работает так же хорошо
  2. Его проще в использовании и легче читать / поддерживать
  3. Нет смысла делать это трудным способом (# 2)

Я могу вспомнить только одну причину, по которой вам может понадобиться второй способ: если вам нужно было иметь возможность заменить DLL на лету, более новой версией или чем-то другим, не выходя из приложения, тогдаВы хотели бы получить точный контроль зерна при выгрузке DLL (чтобы файл мог быть заменен).

Это вряд ли будет требованием, за исключением очень особых случаев.

Bottom LineЕсли вы используете C #, вы принимаете тот факт, что вы даете контроль над инфраструктурой в обмен на возможность сосредоточиться на работе, а не беспокоиться о таких вещах, как DLL или управление памятью.Среда DotNet - это ваш друг, пусть она сделает за вас тяжелую работу и сосредоточит ваши усилия на остальной части кода.

0 голосов
/ 16 апреля 2019

Когда вы вызываете DllImport, LoadLibrary заканчивается для вас, и экспортированная функция (надеюсь) будет найдена в EAT.По сути, во втором примере вы делаете то же самое, что и typedef + GetModuleHandle & GetProcAddress для c / c ++.

Единственная причина, по которой я мог бы подумать о том, чтобы использовать ваш второй метод, заключается в том, что DllMain вашего неуправляемого модуля выполняет код при присоединении к процессу, который вы можете в зависимости от сценария иметь конкретный контроль времени, когдаэтот модуль загружается в ваш процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...