00j*_*0jt 1 c# pinvoke dllimport
我有一个C++ Dll"TheFoo.dll",方法是"Foo()"
我可以通过简单地调用以下方法访问使用此方法的其他C++代码:
Foo();
Run Code Online (Sandbox Code Playgroud)
我相信该方法确实具有:
__declspec( dllexport )
Run Code Online (Sandbox Code Playgroud)
所以,随着我对P/Invoke的阅读,我想我应该能够简单地从我的C#代码中调用相同的方法:
namespace PInvokeExample1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport(@"C:\MyFolder\TheFoo.dll")]
public static extern
void Foo();
private void button1_Click(object sender, RoutedEventArgs e)
{
Foo();
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我收到一个错误:
Unable to find an entry point named 'Foo' in DLL 'C:\MyFolder\TheFoo.dll'.
Run Code Online (Sandbox Code Playgroud)
任何想法为什么没有找到?
C++语言支持重载,就像C#一样.您可以导出函数void Foo(int)和函数void Foo(double).显然,这两个函数不能同时导出为"Foo",DLL的客户端不知道选择哪一个.所以事实并非如此.
C++编译器通过修饰函数的名称来解决这个问题.添加额外的字符使Foo(int)与Foo(double)不同.您可以通过Dumpbin.exe /exports foo.dll从Visual Studio命令提示符运行来查看这些修饰名称,该命令提示符列出了导出函数的名称.假设你的声明是相关的,你会看到?Foo@@YAXXZ.
所以C#程序中的相应声明应该是:
[DllImport("foo.dll", EntryPoint = "?Foo@@YAXXZ",
ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void Foo();
Run Code Online (Sandbox Code Playgroud)
有一些方法可以更改C++函数声明,使C#声明更容易.这实际上不是一个好主意,这些装饰名称实际上有助于捕捉错误.
| 归档时间: |
|
| 查看次数: |
2693 次 |
| 最近记录: |