2

我正在尝试访问 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 (wrapper managed-to-native) PinvokeTesting.MainClass:GetKeyState (int) at PinvokeTesting.MainClass.Main (System.String[] args) [0x00000] in .../Main.cs :11

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

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

4

3 回答 3

3

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

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

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

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

如果您尝试结合 Linux 上 Mono 中的托管 System.Windows.Forms 实现来执行此操作,那么我相当肯定 pinvoking Wine 不会对您有所帮助。SWF 的实现与 Wine 完全不同/独立,两者不会“混合”或以任何方式交互。

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

于 2010-02-27T00:14:53.080 回答
1

正如您所发现的那样,这里的故事有一个简单的寓意……如果使用了 pinvokes,请不要假设代码是跨平台可移植的并且与 wine 兼容!您唯一可以解决的问题是这样的:

使用系统;
使用 System.Runtime.InteropServices;
使用 System.Windows.Forms;

命名空间 PinvokeTesting
{
    类主类
    {
        公共静态无效主要(字符串[]参数)
        {
            Console.WriteLine(GetKeyState((int)Keys.A));
        }

#ifdef WIN32API_NT_5
        [DllImport("user32")]
        私有静态外部短GetKeyState(int vKey);
#别的
        私有静态外部短GetKeyState(int vKey);
#万一
    }
}

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

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

希望这会有所帮助,最好的问候,汤姆。

于 2010-02-27T00:22:22.937 回答