使用MonoMac将自定义本机MacOS X库转换为dll

时间:2015-04-19 22:49:12

标签: c# macos xamarin xamarin-studio monomac

我正在尝试使用本机接口(.xibs)将Windows窗体应用程序移植到MacOS X.此应用程序需要访问具有MacOS X驱动程序的硬件设备,但我希望保留已为Windows版本编写的C#逻辑,以便将来更新应用程序更容易。我已经创建了一个小的Xcode项目来测试如何访问这个设备,然后我让它运行起来,然后我将它转换成.framework并尝试在MonoMac项目中使用它。这证明有点困难。

我主要按照以下教程来确定要采取的步骤,我还复制了示例代码,以确保我不会遇到各种依赖性问题,因为我创建的.framework是一个有点复杂,并按照所有步骤创建一个i386框架(巧合的是我需要以这种方式编译我的驱动程序,因为它已经很老......)称为简单:

http://brendanzagaeski.appspot.com/xamarin/0002.html

这是一个非常简单的类,如下所示:

@implementation Simple
- (NSString *)run:(BOOL *)successful
{
    *successful = YES;
    return @"OK";
}
@end

我已经完成了所有步骤而没有任何问题直到详细说明如何使用sharpie的步骤,因为这已经变为具有不同参数的仅命令行工具。我最终使用以下命令生成.cs文件:

sharpie bind -sdk macosx10.10 -framework Simple.framework -classic -v -c -arch i386

ApiDefinitions.cs如下所示:

using MonoMac.Foundation;

//[Verify (ConstantsInterfaceAssociation)]
partial interface Constants
{
    // extern double SimpleVersionNumber;
    [Field ("SimpleVersionNumber")]
    double SimpleVersionNumber { get; }

    // extern const unsigned char [] SimpleVersionString;
    [Field ("SimpleVersionString")]
    byte[] SimpleVersionString { get; }
}

// @interface Simple : NSObject
[BaseType (typeof(NSObject))]
interface Simple
{
    // -(NSString *)run:(BOOL *)successful;
    [Export ("run:")]
    unsafe string Run (bool* successful);
}

-classic开关立即给了我正确的使用(MonoMac.Foundation)所以我更信任,但我也试过没有。除了使用之外的输出是相同的。

我已经注释掉了验证部分,因为它没有编译,并且意味着警告使用sharpie的人可能需要验证某些内容。根据教程,我也改变了bool *成功反对bool成功。

然后我需要bmac。此工具仅存在于Xamarin.Mac中,如果要在MacMono上使用它,首先需要手动编译MacMono并使用生成的bmac.exe。本教程使用以下命令:

/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/usr/bin/bmac -oSimple.dll --tmpdir=/tmp -baselib=/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/usr/lib/mono/XamMac.dll -r=System.Drawing SimpleBindingDefinition.cs

我已将此更改为以下命令:

mono /Users/Name/Code/monomac/monomac/src/bmac.exe -o Simple.dll --tmpdir=/tmp -baselib=/Users/Name/Code/monomac/monomac/src/MonoMac.dll -r=System.Drawing ApiDefinitions.cs

这会产生以下错误:

   in Method: System.String Run(Boolean*)
error BI0000: Unexpected error - Please file a bug report at http://bugzilla.xamarin.com
// and more

很好,教程已经警告过boolean ref所以我把它改成了:

unsafe string Run (ref bool successful);

现在我留下了完全相同的错误栏关于布尔值的部分:

error BI0000: Unexpected error - Please file a bug report at http://bugzilla.xamarin.com
System.NullReferenceException: Object reference not set to an instance of an object
  at Generator.Generate (System.Type type) [0x00000] in <filename unknown>:0 
  at Generator.Go () [0x00000] in <filename unknown>:0 
  at BindingTouch.Main2 (System.String[] args) [0x00000] in <filename unknown>:0 
  at BindingTouch.Main (System.String[] args) [0x00000] in <filename unknown>:0 

所以它肯定会尝试处理方法运行:并且在某个地方绊倒,但我不确定实际问题从何处开始。 Sharpie转换是否已经错误,或者是我改变ApiDefinitions或调用bmac.exe的方式?


还试图创建一个没有bool ref参数的新框架版本,并删除了这两个版本方法。这并没有改变任何事情。


我试图弄清楚当它编译到位时是否是编译错误。 经过测试:此框架在常规Xcode项目中顺利运行

2 个答案:

答案 0 :(得分:0)

我开始怀疑bmac.exe越来越多,我终于安装了Xamarin.Mac的试用版。这可以通过以下方式获得:http://forums.xamarin.com/discussion/31680/welcome-to-the-xamarin-mac-forums-and-faq#latest但未来可能会发生变化。这还包含bmac的原生版本(没有.exe扩展名),这在我第一次尝试时已经做得更多了。通过一点调整我得到了这个调用,并生成了一个.dll:

/Library/Frameworks/Xamarin.Mac.framework/Versions/1.10.0.18/bin/bmac -o Simple.dll --tmpdir=. \ 
-baselib=/Library/Frameworks/Xamarin.Mac.framework/Versions/1.10.0.18/lib/mono/XamMac.dll  \ 
-r=System.Drawing.dll ApiDefinitions.cs -v -unsafe -target:library

这是我最终使用的.cs文件:

using System;
using System.Drawing;
using MonoMac.Foundation;

namespace OPN200x
{
    // @interface SimpleClass : NSObject
    [BaseType (typeof(NSObject))]
    interface SimpleClass
    {
        // -(NSString *)run;
        [Export ("run")]
        string Run { get; }
    }
}

当我运行应用程序并创建类的实例时,我遇到错误:

Could not create an native instance of the type 'OPN200x.SimpleClass': the native class hasn't been loaded.
It is possible to ignore this condition by setting MonoMac.ObjCRuntime.Class.ThrowOnInitFailure to false.

我不确定它与之相关,但我认为bmac的工作方式很好。

答案 1 :(得分:0)

bmac 现在可以构建好的DLL。在初始化此库的任何实例之前,只是在MonoMac应用程序中缺少加载框架。

if (Dlfcn.dlopen("PathToFrameworksFolder/Simple.framework/Simple", 0) == IntPtr.Zero)
{
Console.Error.WriteLine("Unable to load the dynamic library.");
}

回到:http://brendanzagaeski.appspot.com/xamarin/0002.html并查看此博客的底部,代码类MainClass