Установка dllimport программно в C#

Нет никакого лучшего подхода, только общие и менее общие падежи.

более общий падеж - когда у Вас есть интерфейс класса/функции для объявления/определения. Лучше иметь только один .cpp/.c с определениями и одним заголовком для объявлений. Предоставление их, которых то же имя делает легким понять, что они непосредственно связаны.

, Но это не "правило", это - распространенный способ и самое эффективное почти во всех случаях.

Теперь в некоторых случаях (как шаблонные классы или некоторое крошечное определение структуры) Вам не будет нужен никакой .c/.cpp файл, просто заголовок. У нас часто есть некоторое виртуальное определение интерфейса класса только в заголовочном файле, например, только с виртуальными чистыми функциями или тривиальными функциями.

И в других редких случаях (как гипотетический main.c/.cpp файл), если всегда не требовался бы, чтобы позволять коду от внешней единицы компиляции вызывать функцию данной единицы компиляции. Основная функция является примером (никакой необходимый заголовок/объявление), но существуют другие, главным образом когда это - код, которые "соединяют все другие части вместе", и не назван другими частями приложения. Это очень редко, но в этом случае заголовок не имеет никакого смысла.

9
задан Cœur 17 December 2018 в 09:41
поделиться

7 ответов

Вероятно, этого можно добиться с помощью ключевого слова #if . Если вы определите условный символ компилятора с именем win32 , следующий код будет использовать блок win32, если вы его удалите, он будет использовать другой блок:

#if win32
    private static class ccf_32
    {
        [DllImport(myDllName32)]
        public static extern int func1();
    }
#else    
    private static class ccf_64
    {
        [DllImport(myDllName64)]
        public static extern int func1();
    }
#endif

Это, вероятно, означает, что вы можете удалить обертку класса что у вас есть сейчас:

    private static class ccf
    {
#if win32
        [DllImport(myDllName32)]
        public static extern int func1();
#else    
        [DllImport(myDllName64)]
        public static extern int func1();
#endif
    }

Думаю, для удобства вы могли бы создать конфигурации сборки для управления символом компиляции.

12
ответ дан 4 December 2019 в 06:09
поделиться

Почему бы не обернуть их в метод?

private static class ccf_32_64
{
    private static class ccf_32
    {
        [DllImport(myDllName32)]
        private static extern int func1();
    }

    private static class ccf_64
    {
        [DllImport(myDllName64)]
        private static extern int func1();
    }

    public static int func1()
    {
        if (32bit)
        {
            return ccf_32.func1();
        }
        else
        {
            return ccf_64.func1();
        }
    }
}
2
ответ дан 4 December 2019 в 06:09
поделиться

Один из альтернативных вариантов - иметь как 32-, так и 64-разрядные версии неуправляемой библиотеки DLL с одинаковым именем, но размещать их в отдельных папках в выходных данных сборки (скажем, x86 \ и x64 \).

Затем ваш установщик или другое средство, которое вы распространяете, обновляется, поэтому он знает, как установить правильную DLL для платформы, на которой он устанавливается.

1
ответ дан 4 December 2019 в 06:09
поделиться

Вы не можете сделать это так, как хотите. Атрибут DllImport следует рассматривать как метаданные, которые используются во время компиляции. В результате вы не можете изменять динамически импортируемую DLL.

Если вы хотите, чтобы ваш управляемый код был нацелен на «Любой процессор», вам необходимо либо импортировать 32-битные, и 64-битные библиотеки, упакованные как две разные функции, которые можно вызывать в зависимости от среды выполнения, или использовать некоторые дополнительные вызовы API Win32 для поздней загрузки правильной версии неуправляемой сборки во время выполнения и дополнительные вызовы Win32 для выполнения необходимых методов. Недостатком является то, что у вас не будет поддержки времени компиляции для любого из этих типов кода для обеспечения безопасности типов и т. Д.

0
ответ дан 4 December 2019 в 06:09
поделиться

Хм, мне интересно, могли бы вы создать интерфейс, а затем класс с методами, основанными на 32-битных и 64-битных dll.

Я не уверен, что есть явный метод определения того, используете ли вы 64-разрядную версию, но может работать следующее: разрешить небезопасный код и иметь небезопасную функцию, которая получает указатель на некоторый адрес, а затем определяет, имеет ли указатель размер 4 или 8 байтов. На основе результата определите, какую реализацию интерфейса создать.

0
ответ дан 4 December 2019 в 06:09
поделиться

Вы можете определить, используете ли вы 64-битные биты, проверив размер типа IntPtr (который в любом случае называется native int). Затем вы можете загрузить соответствующую DLL с помощью импортированного вызова LoadLibraryW, получить указатель на функцию с помощью GetProcAddress, а затем проверить Marshal.GetDelegateForFunctionPointer

Это не так сложно, как может показаться. Вам необходимо DllImport как LoadLibraryW, так и GetProcAddress.

0
ответ дан 4 December 2019 в 06:09
поделиться

I prefer to do this by using the LoadLibrary call from kernel32.dll to force a particular DLL to load from a specific path.

If you name your 32-bit and 64-bit DLLs the same but placed them in different paths, you could then use the following code to load the correct based on the version of Windows you are running. All you need to do is call ExampleDllLoader.LoadDll() BEFORE any code referencing the ccf class is referenced:

private static class ccf
{
    [DllImport("myDllName")]
    public static extern int func1();
}

public static class ExampleDllLoader
{
    [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
    private extern static IntPtr LoadLibrary(string librayName);

    public static void LoadDll()
    {
        String path;

        //IntPtr.Size will be 4 in 32-bit processes, 8 in 64-bit processes 
        if (IntPtr.Size == 4)
            path = "c:/example32bitpath/myDllName.dll";
        else
            path = "c:/example64bitpath/myDllName.dll";

        LoadLibrary(path);
    }
}
18
ответ дан 4 December 2019 в 06:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: