【问题标题】:Make a class defined in extern "C" block able to reference method outside使在外部“C”块中定义的类能够引用外部方法
【发布时间】:2013-06-05 18:41:32
【问题描述】:

我正在尝试为 Unity3d iOS 编写一个简单的插件,您可能听说过该流式视频。我实际上设法做到了,流媒体视频位有效。

现在我正在尝试添加作为插件一部分的功能,以检测滑动手势并向 Unity 发送消息。我没有使用 Objective C 的经验,目前对学习细节不感兴趣,因为我只是想为这个特定问题找到解决方案。

所以我已经设法在谷歌上找到了流式传输实际视频所需的所有内容,以及一些用于注册滑动手势的代码。问题在于,在定义 UISwipeGestureRecognizer 时,您应该为其分配一个操作方法。但是执行视频流的功能是在 extern "C" 块中定义的,这是必需的,以便可以在 Unity 中引用它。

虽然必须在 iOS 应用程序的常规框架中定义(我认为)分配给手势识别器的方法,但我怀疑这会产生手势识别器类不知道在外部定义的方法的问题extern "C" 块。

所以现在当我运行它时,视频开始流式传输,但一旦我开始滑动屏幕,它就会崩溃。大概是因为分配的方法不能被引用是我的猜测。

我的问题是...我该如何做到这一点,也许有一些我不知道的显而易见的事情?重要的是让它在外部“C”块中定义的函数中工作,因为这毕竟是 Unity 所要求的。

这是我到目前为止编写的实际代码:

http://www.hastebin.com/ragocorola.m

推测loadLevel方法应该如何声明?

extern "C" {


    void _playVideo(const char *videoFilepath)
    {

        NSURL *url = [NSURL URLWithString:CreateNSString(videoFilepath)];

        MPMoviePlayerController *player = [[MPMoviePlayerController alloc]  
        initWithContentURL:url];

        player.controlStyle = MPMovieControlStyleFullscreen;
        player.view.transform = CGAffineTransformConcat(player.view.transform, 
                                CGAffineTransformMakeRotation(M_PI_2));

        UIWindow *backgroundWindow = [[UIApplication sharedApplication] keyWindow];

        [player.view setFrame:backgroundWindow.frame];
        [backgroundWindow addSubview:player.view];



       UISwipeGestureRecognizer * swipe = [[UISwipeGestureRecognizer alloc] 
       initWithTarget:swipe action:@selector(loadLevel:)];

       [swipe setDirection:(UISwipeGestureRecognizerDirectionUp | 
        UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionLeft 
       |UISwipeGestureRecognizerDirectionRight)];


       [player.view addGestureRecognizer:swipe];

       [player play];


    }


}

【问题讨论】:

  • 代码中的一条注释说,“extern C”块仅在 .mm 或 .cpp 文件中需要。你那里有一个 .m 文件,所以它是绝对必要的吗?
  • Extern C 块是必需的,以便在 Unity3D 中引用该函数。它不是一个 .m 文件 btw 它是一个 .mm 文件,这只是巧合生成的链接 hastebin。我的 Xcode 项目中的文件名为 VideoPlugin.mm
  • 该函数在代码中被引用,以便在 Unity3D 中使用,如下所示: [DllImport ("__Internal")] private static extern void _playVideo (string videoFilepath);

标签: ios methods mpmovieplayercontroller extern


【解决方案1】:

您的问题是 swipe 在您将其作为目标传递时未定义。谁知道当它通过时堆栈上的内容是什么?这会导致在您滑动时将方法发送到内存中的错误位置。

UISwipeGestureRecognizer * swipe = [[UISwipeGestureRecognizer alloc] 
initWithTarget:swipe action:@selector(loadLevel:)];

这相当于:

id undefinedTarget;
UISwipeGestureRecognizer * swipe = [[UISwipeGestureRecognizer alloc] 
    initWithTarget:undefinedTarget action:@selector(loadLevel:)];

您的目标需要是定义loadLevel: 方法的类的实例。


编辑(在追踪您的链接之后):即VideoPlugin 的一个实例。

虽然您将遇到的第二个问题是方法loadLevel:loadLevel 不同。确保它们是一致的。

【讨论】:

  • 非常感谢您的评论。我有点怀疑这应该是一个问题,但是我发现的所有示例都将 self 声明为目标,我不知道它是什么,并且如果我尝试过,也被 Xcode 确定为未声明的标识符。您能否为我提供一个示例来解释如何创建一个定义 LoadLevel: 方法的类(我怀疑是 - (void)loadLevel ),然后创建一个实例?我将不胜感激:)
  • 这在我的代码上下文中有意义吗? VideoPlugin *swipetarget = [[VideoPlugin alloc] init];
  • 很高兴你能成功。显然,您在创建上述实例时处于正确的轨道上。 self 变量是类的所有方法的隐藏参数,并引用您正在执行的实例。它仅在方法内有效;您在 C 函数中,因此没有 self 变量。
  • 如果这个答案是您所需要的,请继续并“接受”它。 stackoverflow.com/about
猜你喜欢
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
相关资源
最近更新 更多