3

我想从objective-c调用ac函数并将objective-c函数作为回调传递

问题是这个函数有一个回调作为参数,所以我必须将objective-c函数作为回调传递给c函数

这是c函数的标题

        struct mg_context *mg_start(const struct mg_callbacks *callbacks,
                        void *user_data,
                        const char **configuration_options);

这是我尝试称呼它的地方

- (void)serverstarted
{
    NSLog(@"server started");
}


- (IBAction)startserver:(id)sender {
   NSLog(@"server should start");
   const char *options[] =
   {
       "document_root", "www",
       "listening_ports", "8080",
        NULL
   };
   mg_start(serverstarted(), NULL, options);
  }

我已经尝试了几种方法来做到这一点,并在网上搜索只是得到一个线索如何做到这一点,但没有运气

这是我在代码中包含的库

https://github.com/valenok/mongoose

4

2 回答 2

5

您的主要问题是 的第一个参数mg_start(),在声明中描述为const struct mg_callbacks *callbacks。您正在尝试将指针传递给函数。(实际上,您正试图将调用结果传递给该函数,这离标记更远。)这不是它所说的:它说的是一个指向结构(特别是mg_callbacks结构)的指针。

https://github.com/valenok/mongoose/blob/master/examples/hello.c上的示例代码向您展示了如何配置此结构。您必须创建结构并将指向回调函数的指针放入其中。然后传递该结构的地址。

您的代码的其他问题:您的回调函数本身都是错误的:

- (void)serverstarted
{
    NSLog(@"server started");
}

这里需要的是一个像这样声明的 C 函数:int begin_request_handler(struct mg_connection *conn),也就是说,它需要一个指向mg_connection结构的指针作为参数。您serverstarted不仅不采用该参数,甚至不是 C 函数!这是一种 Objective-C 方法,一种完全不同的动物。您在标题和问题中使用术语“Objective-C 函数”具有误导性;C 有函数,Objective-C 有方法。您将在此处编写的代码中不会使用任何 Objective-C。

我建议你在这里做的是一开始就盲目hello.c地复制这个例子。然后慢慢地、一点点地修改事物的内容/名称,使其演变成你自己的代码。当然,学习 C 语言也会有所帮助,但您可能只需仔细复制即可。

于 2013-04-19T14:27:06.877 回答
3

正如 matt 已经说过的,您不能将 Objective-C 方法作为回调传递给需要 C 函数的地方。Objective-C 方法是特殊函数,特别是接收者(“self”)作为第一个参数隐式传递给函数。

因此,要将 Objective-C 方法用作请求处理程序,您需要一个(中间)C 函数作为处理程序,并且您必须self使用参数传递给该函数user_data。然后 C 函数可以调用 Objective-C 方法:

// This is the Objective-C request handler method:
- (int)beginRequest:(struct mg_connection *)conn
{
    // Your request handler ...
    return 1;
}

// This is the intermediate C function:
static int begin_request_handler(struct mg_connection *conn) {
    const struct mg_request_info *request_info = mg_get_request_info(conn);
    // Cast the "user_data" back to an instance pointer of your class:
    YourClass *mySelf = (__bridge YourClass *)request_info->user_data;
    // Call instance method:
    return [mySelf beginRequest:conn];
}

- (IBAction)startserver:(id)sender
{
    struct mg_callbacks callbacks;
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.begin_request = begin_request_handler;
    const char *options[] =
    {
        "document_root", "www",
        "listening_ports", "8080",
        NULL
    };
    // Pass "self" as "user_data" argument:
    mg_start(&callbacks, (__bridge void *)self, options);
}

评论:

  • 如果您不使用 ARC(自动引用计数),那么您可以省略(__bridge ...) 强制转换。
  • 您必须确保在服务器运行时不会释放您的类的实例(“self”)。否则在YourClass *mySelf 调用请求处理程序时将是无效的。
于 2013-04-19T17:23:07.280 回答