P / Invoke和Mono:EntryPointNotFoundException

时间:2010-02-27 00:11:15

标签: .net mono pinvoke wine

我正在尝试在Kubuntu Linux上访问某些user32函数的Wine实现。我安装了Wine 1.1.31软件包。当尝试在MonoDevelop中运行这个简单的测试程序时,我得到一个System.EntryPointNotFoundException

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace PinvokeTesting
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Console.WriteLine(GetKeyState((int)Keys.A));
        }

        [DllImport("user32")]
        private static extern short GetKeyState(int vKey);
    }
}

这是输出:

  

未处理的例外情况:   System.EntryPointNotFoundException:   GetKeyState at(包装器   托管到本机)   PinvokeTesting.MainClass:函数GetKeyState   (int)at   PinvokeTesting.MainClass.Main   (System.String [] args)[0x00000] in   ... / Main.cs:11

该功能应该在那里,但它找不到它。有任何想法吗?我做了很多搜索,没有发现任何有用的东西。在这些问题上(或者我正在寻找错误的东西),文档似乎相当稀疏​​。

编辑:我没有尝试将P / Invoke与Winforms结合使用,我需要P / Invoke中的Wine中还有一些其他功能。我只是想让Mono P / Invoke到Wine工作。

3 个答案:

答案 0 :(得分:3)

如果您尝试在Linux上的Mono中与受管理的System.Windows.Forms实现结合使用,那么我相当确定正在使用Wine并不会对您有所帮助。 SWF与Wine完全不同/分开实施,两者不“混合”或以任何方式进行交互。

我建议你找到另一种方法来实现你想要做的事情。

答案 1 :(得分:3)

葡萄酒库与单声道完全不相容。如果你需要在Linux上使用wine libs,你需要获得windows版本的mono并在wine下运行它。

这与Winforms没有任何关系,它适用于任何葡萄酒库。

至于问题的实际解决方案:

  • 不要使用已建议的#ifdef WIN32API_NT_5技巧,而是使用运行时检测并调用一种方法或另一种方法,具体取决于您是在Windows下运行还是在不同操作系统下运行:拥有一个二进制文件值得1 - 循环运行时惩罚(如果将操作系统标志存储在一个静态的readnly字段中,则会更多地为您优化检查)。
  • 如果您希望代码是可移植的,则需要应对不同的操作系统模型,因为并不总是能够以简单或完全兼容的方式从另一个系统实现ant调用。 例如,在GetKeyState()情况下,您可能需要连接键盘事件 并自己记录按下/释放状态。
  • 考虑不同的方法来做同样的事情,例如,您确定mscorlib中的标准Console类不能提供程序中所需的功能吗?

答案 2 :(得分:1)

这里的故事有一个简单的道德,因为你已经发现...如果使用了pinvokes,不要假设代码是跨平台便携式和葡萄酒兼容的!你能解决的唯一问题就是这样:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace PinvokeTesting
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Console.WriteLine(GetKeyState((int)Keys.A));
        }

#ifdef WIN32API_NT_5
        [DllImport("user32")]
        private static extern short GetKeyState(int vKey);
#else
        private static extern short GetKeyState(int vKey);
#endif
    }
}

创建某种包装来代替Win32API pinvoke签名。仅仅因为它引用System.Windows.Forms并不意味着WIN32API pinvokes在Wine下可以工作,因为GUI方面的各种底层接口是不同的,并且不能保证是可移植的。

如果你想让这个跨平台友好,那么定义开关'WIN32API_NT_5'或你想要自己选择的任何东西。

希望这有帮助, 最好的祝福, 汤姆。