Очевидно, заявления Declare и DllImport в основном одинаковы. Вы можете использовать то, что вы предпочитаете.
Ниже приводится обсуждение нескольких пунктов, которые могут работать немного по-разному в каждом, которые могут влиять на предпочтение одного над другим:
Я начал со статьи из MSDN относительно Visual Studio 2003 под названием Using the DllImport Attribute. (Немного устарел, но поскольку оператор DllImport, по-видимому, возник в .NET, было бы целесообразно вернуться к началу.)
Учитывая пример DllImport заявление:
[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);
Он говорит, что если значение EntryPoint остается вне, CLR будет искать имя функции (MessageBox, в данном случае) по умолчанию , Однако в этом случае, поскольку был указан CharSet из Unicode, CLR бы FIRST искал функцию под названием «MessageBoxW» - «W», указывающую тип возврата Unicode. (Версия типа ANSI возвращаемого типа будет «MessageBoxA».) Если «MessageBoxW» не было найдено, THEN CLR будет искать функцию API, фактически называемую «MessageBox».
Современные особенности о классе DllImportAttribute можно найти здесь, где я рассматривал .NET Framework 4 версии: DLLImportAttribute Class
Ключевой комментарий в разделе Замечаний этой страницы 4 .NET Framework является то, что:
Вы применяете этот атрибут непосредственно к определениям методов C# и C++; однако компилятор Visual Basic испускает этот атрибут, когда вы используете оператор Declare.
Таким образом, по крайней мере, так же,
Существует также важное примечание на этой странице:
DllImportAttribute не поддерживает маршалинг родовых типов.
Таким образом, если вы хотите использовать общий тип, вам нужно будет использовать оператор Declare
.
Далее я направился к информации заявления Declare. Визуальное версия Studio 2010 (Visual Basic Информация заявление) здесь: Declare Statement
Ключевой пункт здесь был это примечание:
Вы можете использовать Объявите только на уровне модуля. Это означает, что контекст объявления для внешней ссылки должен быть классом, структурой или модулем и не может быть исходным файлом, пространством имен, интерфейсом, процедурой или блоком.
Очевидно, что если вы хотите, чтобы настроить вызов API вне класса, структуры или модуля, вы должны использовать оператор DllImport вместо Declare
.
Пример Declare
заявление на этой странице:
Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
После этого примера эта маленькая пикантная информация:
DllImportAttribute обеспечивает альтернативный способ использования функции в неуправляемом коде. Следующий пример объявляет импортированную функцию без использования оператора Declare.
, за которым следует, конечно, пример использования DllImport.
Что касается результатов Unicode и ANSI, в соответствии с этой страницей Declare, если вы укажете значение CharSet (доступно в Declare, но не показано в примере выше), CLR выполнит автоматический поиск по типу автоматического имени, который выполняет DllImport, для Unicode или ANSI.
Если вы не укажете значение НаборСимволов в Declare
заявления, то вы должны убедиться, что ваше имя функции в Declare таким же, как имя функции в файле заголовок фактической функции API, либо вы должны specifiy в Alias
значение, соответствующее фактическому имени функции в файле заголовка (как показано в примере выше).
Я не смог найти какую-либо конкретную документацию Microsoft, в которой указывалось, что либо DllImport, либо Declare были предпочтительны или даже рекомендованы друг другу в любой ситуации, отличной от отмеченной выше.
Мой вывод, таким образом, является:
1) Если вам не нужно поместить определение в одном из мест не может быть использована Declare
заявление, либо метод будет работать нормально,
и
2) если вы используете DllImport, убедитесь, что вы указали требуемое значение CharSet (Unicode или ANSI), или вы можете получить неожиданные результаты.
Это отличная запись и отличные исследования. Большое спасибо! – Mike