C# 使用可变数量的函数

C# 使用可变数量的函数,c#,dll,unmanaged,C#,Dll,Unmanaged,例如:在app1中,用户创建函数_1()和函数_2()。然后在app2中,用户想要调用函数_2()。我在谷歌上搜索,唯一发现的是写下以下代码: 您必须使用一些PInvoke代码来加载DLL(),获取函数指针(),并获取可以调用的委托。Damien编写的完整示例。。。请注意,只有当方法具有所有相同的签名时(在本例中为void function_X()),它才起作用。此外,探索dll以发现导出了哪些方法是“困难的”,因此,如果您已经知道dll中应该有哪些方法,则更好 [DllImport("kern

例如:在app1中,用户创建函数_1()和函数_2()。然后在app2中,用户想要调用函数_2()。我在谷歌上搜索,唯一发现的是写下以下代码:


您必须使用一些PInvoke代码来加载DLL(),获取函数指针(),并获取可以调用的委托。

Damien编写的完整示例。。。请注意,只有当方法具有所有相同的签名时(在本例中为
void function_X()
),它才起作用。此外,探索dll以发现导出了哪些方法是“困难的”,因此,如果您已经知道dll中应该有哪些方法,则更好

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

// Set the correct calling convention
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DllMethodDelegate();

IntPtr dll = LoadLibrary(@"PathToYourDll.DLL");

if (dll == IntPtr.Zero)
{
    throw new Exception();
}

string methodName = "function_1";

IntPtr method = GetProcAddress(dll, methodName);

if (method == IntPtr.Zero)
{
    throw new Exception();
}

DllMethodDelegate method2 = (DllMethodDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(DllMethodDelegate));

// Now you can do method2();
请注意,您必须在
dllmethodelegate()
定义中设置正确的调用约定。通常,dll方法应该是
StdCall

您编写的方法的签名为:

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate int DllMethodDelegate(char cmd, ref IntPtr out_address);
请注意,“填充”out\U地址非常复杂(复杂)

对于第三个示例,您可以这样做(但我不确定)

object value2 = value;
而不是

int[] value2 = new int[] { value };

装箱和
GCHandle
的交互并没有很好的文档记录,但似乎很有效。C#规范4.3似乎可以。。。但我不相信它,而且这项技术似乎在“.NET和COM:完整的互操作性指南”一书中有描述,在“获取值类型的地址”一章中(这一章可以在google中搜索,使用我给出的确切章节标题。示例在VB.NET中,但阅读起来非常清楚)

您可以使用dbghelp dll中的SymEnumerateSymbols64来获取dll中现有函数的列表。然后用户可以选择运行哪个函数

您可以在此处找到更详细的说明:

因此,这里的明显推论是,这是一个非托管(非.NET DLL?)运行时可以有选择地加载DLL的唯一方法是使用LoadLibrary,尽管我不能严格确定这是否符合您的要求。在(不得不发布缩短链接)上有一篇很好的文章(如果有点过时的话)详细介绍了这一点。@ale93它完全被所谓的。。。尝试将其粘贴到问题中。@ale93如果您有多个签名类型(在本例中为多个返回类型==多个签名),则必须通过多个委托类型手动处理它们。。。而且
void**
,我认为这在C#中不容易实现。@ale93添加了一个在三种模式下调用的示例。
object value2 = value;
int[] value2 = new int[] { value };