Xamarin - 错误构建绑定库 Messaging.g.cs

Posted

技术标签:

【中文标题】Xamarin - 错误构建绑定库 Messaging.g.cs【英文标题】:Xamarin - error building a binding library Messaging.g.cs 【发布时间】:2016-09-24 12:30:15 【问题描述】:

在为 Xamarin.ios 构建绑定库时遇到问题。基本上我需要构建它以将dll 引用到一个单独的项目中。

这是我的示例project。

问题是自动生成的Messaging.g.cs 出现错误并完成中线:

//
// Auto-generated from generator.cs, do not edit
//
// We keep references to objects, so warning 414 is expected

#pragma warning disable 414

using System;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using UIKit;
using GLKit;
using Metal;
using MapKit;
using ModelIO;
using Security;
using SceneKit;
using CoreVideo;
using CoreMedia;
using QuickLook;
using Foundation;
using CoreMotion;
using ObjCRuntime;
using AddressBook;
using CoreGraphics;
using CoreLocation;
using AVFoundation;
using NewsstandKit;
using CoreAnimation;
using CoreFoundation;

namespace ApiDefinition 
    partial class Messaging 
        static internal System.Reflection.Assembly this_assembly = typeof (Messaging).Assembly;

        const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib";

        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static IntPtr IntPtr_objc_msgSend (IntPtr receiever, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static IntPtr IntPtr_objc_msgSendSuper (IntPtr receiever, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static IntPtr IntPtr_objc_msgSend_IntPtr (IntPtr receiever, IntPtr selector, IntPtr arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static IntPtr IntPtr_objc_msgSendSuper_IntPtr (IntPtr receiever, IntPtr selector, IntPtr arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static void void_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static void void_objc_msgSendSuper_IntPtr (IntPtr receiver, IntPtr selector, IntPtr arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static int int_objc_msgSend (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static int int_objc_msgSendSuper (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static void void_objc_msgSend_int (IntPtr receiver, IntPtr selector, int arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static void void_objc_msgSendSuper_int (IntPtr receiver, IntPtr selector, int arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static float float_objc_msgSend (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static float float_objc_msgSendSuper (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static void void_objc_msgSend_float (IntPtr receiver, IntPtr selector, float arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static void void_objc_msgSendSuper_float (IntPtr receiver, IntPtr selector, float arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static bool bool_objc_msgSend (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static bool bool_objc_msgSendSuper (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static void void_objc_msgSend_bool (IntPtr receiver, IntPtr selector, bool arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static void void_objc_msgSendSuper_bool (IntPtr receiver, IntPtr selector, bool arg1);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static global::System.Double Double_objc_msgSend (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")]
        public extern static global::System.Double Double_objc_msgSendSuper (IntPtr receiver, IntPtr selector);
        [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
        public extern static void vo

我还关注了Xamarin的官方演练。

我正在尝试构建的项目的原始 repo 是 here,它是原始 Objectice-C here 的绑定项目。

我无法弄清楚为什么 Messaging.g.cs 会出错并阻止构建完成。

任何帮助将不胜感激。

一切顺利,

约翰

【问题讨论】:

【参考方案1】:

我已经设法解决了这个问题。

我希望这个答案在未来对其他 Xamarin 开发人员有所帮助。

如果您使用的是 Objective C 绑定库,则应使用 XCode 构建并使用 Objective Sharpie 可用的 here 生成 ApiDefinition.cs 和 StructsAndEnums.cs。

我遇到的问题是自动生成的代码无法正确处理Delegates。此外,[Native] 属性导致解释器使用不兼容的数据类型 - 即 enum 结构与 uint

结合上述问题,我还尝试在同一个项目中绑定多个.a 静态库。

因此,您需要在 Objective Sharpie 生成的 C# 文件中重构一些内容:

删除任何重复的方法签名在我的示例中,该工具生成了以下代码:

        // @optional -(BOOL)revealControllerPanGestureShouldBegin:(SWRevealViewController *)revealController;
        [Export("revealControllerPanGestureShouldBegin:")]
        bool RevealController(SWRevealViewController revealController);

        // @optional -(BOOL)revealControllerTapGestureShouldBegin:(SWRevealViewController *)revealController;
        [Export("revealControllerTapGestureShouldBegin:")]
        bool RevealController(SWRevealViewController revealController);

而为了避免编译器抛出重复的方法错误,它应该是:

        // @optional -(BOOL)revealControllerPanGestureShouldBegin:(SWRevealViewController *)revealController;
        [Export("revealControllerPanGestureShouldBegin:")]
        bool RevealControllerPanGestureShouldBegin(SWRevealViewController revealController);

        // @optional -(BOOL)revealControllerTapGestureShouldBegin:(SWRevealViewController *)revealController;
        [Export("revealControllerTapGestureShouldBegin:")]
        bool RevealControllerTapGestureShouldBegin(SWRevealViewController revealController);

接下来,查找工具生成枚举结构的任何示例,该结构继承自不受支持的原语。

所以,例如:

[Native]
public enum FrontViewPosition : uint

    LeftSideMostRemoved,
    LeftSideMost,
    LeftSide,
    Left,
    Right,
    RightMost,
    RightMostRemoved

更改为public enum FrontViewPosition : ulong

接下来删除任何[Verify] 装饰。

最后,我发现Objective Sharpie对扩展方法的处理很差,导致生成的代码试图创建一个内部带有虚拟方法的静态类......

要修复,请查找[Category] 的所有实例,例如:

// @interface SWRevealViewController (UIViewController)
[Category]
[BaseType(typeof(UIViewController))]
partial interface UIViewController_SWRevealViewController

    // -(SWRevealViewController *)revealViewController;
    [Export("revealViewController")]
    SWRevealViewController RevealViewController get; ;

把它改成

// @interface SWRevealViewController (UIViewController)
[Category]
[BaseType(typeof(UIViewController))]
partial interface UIViewController_SWRevealViewController

    // -(SWRevealViewController *)revealViewController;
    [Export("revealViewController")]
    SWRevealViewController RevealViewController();

现在清理并重建,自动生成的代码现在将正确编译。在任何需要的项目中引用绑定 dll 以使用它。

如果有人想在 Xamarin 中使用 SWRevealViewController 库,那么为了节省您的时间,您可以使用我的 repo here。

祝你好运,玩得开心。

约翰

【讨论】:

以上是关于Xamarin - 错误构建绑定库 Messaging.g.cs的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Android Java绑定库运行时失败访问本机库

为 Xamarin 创建 Android 绑定时出现问题

Xamarin.Android之绑定库教程

用于 swift 库的 Xamarin.iOS 绑定

Xamarin 是不是支持 Xamarin Android 绑定库中的 Kotlin 协程?

在Xamarin iOS的Visual Studio App Center中构建失败:只有在使用/ unsafe进行编译时才会出现不安全的代码