C# DllImport 或 LoadLibrary 以获得最佳性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16518943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:12:37  来源:igfitidea点击:

DllImport or LoadLibrary for best performance

c#dllimportloadlibrary

提问by apocalypse

I have external .DLL file with fast assembler code inside. What is the best way to call functions in this .DLL file to get best performance?

我有外部 .DLL 文件,里面有快速的汇编代码。调用此 .DLL 文件中的函数以获得最佳性能的最佳方法是什么?

回答by Igor Minakov

I think DLLImport and LoadLibrary have different goals. If you use native .dll, you should use DllImport. If you use .NET assembly, you should use LoadAssembly.

我认为 DLLImport 和 LoadLibrary 有不同的目标。如果您使用本机 .dll,则应使用 DllImport。如果您使用 .NET 程序集,则应使用 LoadAssembly。

Actually, you can dynamically load native assembly too, see this example: dynamically-calling-an-unmanaged-dll-from-.net

实际上,您也可以动态加载本机程序集,请参见此示例: dynamic-calling-an-unmanaged-dll-from-.net

回答by David Heffernan

The only way to answer this question is to time both options, a task which is trivially easy. Making performance predictions without timing is pointless.

回答这个问题的唯一方法是为两个选项计时,这是一项非常简单的任务。在没有时间安排的情况下进行性能预测是没有意义的。

Since we don't have your code, only you can answer your question.

由于我们没有您的代码,因此只有您可以回答您的问题。

回答by Ryan Mann

Assuming your target platform is the same as said native dll. You can use DLLImport to pinvoke LoadLibrary and use LoadLibrary to load the native dll into your process. Then use DllImport to pinvoke GetProcAddress.

假设您的目标平台与本机 dll 相同。您可以使用 DLLImport 来调用 LoadLibrary 并使用 LoadLibrary 将本机 dll 加载到您的进程中。然后使用 DllImport 调用 GetProcAddress。

Then you can define delegates for all the methods exported in said dll that you want to call.

然后,您可以为要调用的所述 dll 中导出的所有方法定义委托。

Next you use the Marshal.GetDelegateForFunctionPointer to set your delegate from GetProcAddress.

接下来,您使用 Marshal.GetDelegateForFunctionPointer 从 GetProcAddress 设置您的委托。

You create a static class that does this stuff once in the constructor. Then you can call your delegates to invoke the native exported functions in the dll, without having DllImport on everything. Much cleaner, and I'm pretty sure it's a lot faster and will probably completely bypass before mentioned parameter checks.

您创建一个静态类,在构造函数中执行一次这些操作。然后,您可以调用您的委托来调用 dll 中的本机导出函数,而无需对所有内容进行 DllImport。更干净,我很确定它要快得多,并且可能会在提到的参数检查之前完全绕过。

SO you would have a slow initialization, but once loaded, would run fast imo. Haven't tested this.

所以你的初始化速度会很慢,但是一旦加载,就会快速运行imo。没有测试过这个。

Here's a blog on it from my source.

这是来自我的消息来源的博客。

http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx

http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx

回答by Burmese Bug

Your DLL might be in python or c++, whatever , do the same as follow.

你的 DLL 可能是 python 或 c++,不管怎样,做同样的事情。

This is your DLL file in C++.

这是你的 C++ DLL 文件。

header:

标题:

extern "C" __declspec(dllexport) int MultiplyByTen(int numberToMultiply);

Source code file

源代码文件

#include "DynamicDLLToCall.h"

int MultiplyByTen(int numberToMultiply)
{
    int returnValue = numberToMultiply * 10;
    return returnValue;
} 

Take a look at the following C# code:

看看下面的 C# 代码:

static class NativeMethods
{
    [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);
}

class Program
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate int MultiplyByTen(int numberToMultiply);

    static void Main(string[] args)
    {
            IntPtr pDll = NativeMethods.LoadLibrary(@"PathToYourDll.DLL");
            //oh dear, error handling here
            //if (pDll == IntPtr.Zero)

            IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "MultiplyByTen");
            //oh dear, error handling here
            //if(pAddressOfFunctionToCall == IntPtr.Zero)

            MultiplyByTen multiplyByTen = (MultiplyByTen)Marshal.GetDelegateForFunctionPointer(
                                                                                    pAddressOfFunctionToCall,
                                                                                    typeof(MultiplyByTen));

            int theResult = multiplyByTen(10);

            bool result = NativeMethods.FreeLibrary(pDll);
            //remaining code here

            Console.WriteLine(theResult);
    }
}