2010-02-27 72 views
2

我想在Kubuntu Linux上访问一些user32函数的Wine实现。我安装了Wine 1.1.31软件包。当尝试在MonoDevelop中运行这个简单的测试程序时,我得到一个System.EntryPointNotFoundExceptionP/Invoke和单声道: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 (INT): 函数GetKeyState在(包装纸 管理到本机) PinvokeTesting.MainClass PinvokeTesting.MainClass.Main (System.String [] args)[0x00000] in .../Main.cs:11

函数应该在那里,但它没有找到它。有任何想法吗?我做了很多搜索,没有发现任何有用的东西。文档似乎对这些问题相当稀少(无论是或我正在寻找错误的东西)。

编辑:我并不想使用的P/Invoke与的WinForms组合,也有葡萄酒其他一些功能,我需要的P/Invoke来。我只是想让Mono P/Invoke to Wine工作。

回答

3

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

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

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

  • 如果你正在运行时,不要使用已建议的#ifdef WIN32API_NT_5把戏,而不是使用运行时检测并调用一个方法或其他依赖在windows下或不同操作系统下:单个二进制文件值得1个周期的运行时间损失(如果将操作系统标志存储在静态readnly字段中,则monoo会优化您的检查)。
  • 如果您希望自己的代码是可移植的,那么您需要应对不同的操作系统模型,因为通过简单或完全兼容的方式实现另一个系统的蚂蚁通话并非总是可能。 例如,在GetKeyState()情况下,您可能需要连接键盘事件 并自己记录按下/释放状态。
  • 考虑不同的方法来做同样的事情,例如,你确定mscorlib中的标准Console类没有提供你在程序中需要的功能吗?
+0

感谢您的解释。我试图调用'GetKeyState'的唯一原因是因为我试图从Wine中实际得到P/Invoked中的任何*函数,而不是因为我真的想要使用它。有趣的是,显然Mono能够加载'libuser32.so',但无法加载该函数。 IIRC,大约两年前,我能够得到P/Invoke到Wine库的工作。 (或许现在的问题与我现在的设置有关?)无论如何,我想我会寻找一条替代Wine的路线。 (此外,Wine不会成为我的程序的依赖项)。 – 2010-02-27 18:08:54

+0

Mono能够重定向P/Invoke调用,并且特别是它会自动将user32.dll调用重定向到辅助共享库,该辅助共享库现在只包含少数工作函数。这就是为什么DLL似乎被加载,但没有找到符号。 对于某些情况下,您可能可以从wine dll中加载符号,只是使用它可能不起作用,或者可能会导致运行时崩溃或使其他事情无法正常工作。它不被支持,可能永远不会,所以不要认为任何不是深夜实验的程序都可以遵循这条路径。 – lupus 2010-02-28 08:26:05

3

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

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

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'或任何你想自己选择的任何东西,如果你想使这个跨平台友好。

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