如何将结构传递到browse_callback,然后进一步向下传递到avahi中的resolve_callback?

Posted

技术标签:

【中文标题】如何将结构传递到browse_callback,然后进一步向下传递到avahi中的resolve_callback?【英文标题】:How do I pass a struct into the browse_callback and then further down to resolve_callback in avahi? 【发布时间】:2021-10-12 19:02:45 【问题描述】:

每当服务在 avahi 中成功解析时,我想填充一个小部件。由于填充所需的大部分信息都在 resolve_callback() 中可用,因此我需要在其中显示此小部件。但是 resolve_callback() 作为回调不接受任何我可以修改的参数。它由 avahi_service_resolver_new() 自动调用。

static void resolve_callback(
    AvahiServiceResolver *r,
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *address,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    PpDnsWindow *self)

    assert(r);
    /* Called whenever a service has been resolved successfully or timed out */
    switch (event)
    
    case AVAHI_RESOLVER_FAILURE:
         fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
         break;
    case AVAHI_RESOLVER_FOUND:
    
        // here I'll be using the self struct

        char a[AVAHI_ADDRESS_STR_MAX], *t;
        fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
        avahi_address_snprint(a, sizeof(a), address);
        t = avahi_string_list_to_string(txt);
        fprintf(stderr,
                "\t%s:%u (%s)\n"
                "\tTXT=%s\n"
                "\tcookie is %u\n"
                "\tis_local: %i\n"
                "\tour_own: %i\n"
                "\twide_area: %i\n"
                "\tmulticast: %i\n"
                "\tcached: %i\n",
                host_name, port, a,
                t,
                avahi_string_list_get_service_cookie(txt),
                !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
                !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
                !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
                !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
                !!(flags & AVAHI_LOOKUP_RESULT_CACHED));
        avahi_free(t);
    
    
    avahi_service_resolver_free(r);


static void browse_callback(
    AvahiServiceBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *name,
    const char *type,
    const char *domain,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    PpDnsWindow *self)

    AvahiClient *c = self->client;
    assert(b);
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
    switch (event)
    
    case AVAHI_BROWSER_FAILURE:
        fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
        return;
    case AVAHI_BROWSER_NEW:
        fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
        /* We ignore the returned resolver object. In the callback
               function we free it. If the server is terminated before
               the callback function is called the server will free
               the resolver for us. */
        if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, self)))
            fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
        break;
    case AVAHI_BROWSER_REMOVE:
        fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
        break;
    case AVAHI_BROWSER_ALL_FOR_NOW:
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
        fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
        break;
    

我尝试在此函数定义中将AVAHI_GCC_UNUSED void* userdata 修改为PpDnsWindow* self,然后像这样将PpDnsWindow传递给这些函数-

/* Create the service browser */
  if (!(sb = avahi_service_browser_new(self->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, browse_callback, self)))
  
      fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(self->client)));
      destroy(self);
  

但这会导致使用AVAHI_RESOLVER_FAILURE 解决故障。

我不想将小部件设为全局,因为通常不鼓励使用全局变量。有什么方法可以实现吗?

【问题讨论】:

回调通常提供回调的上下文指针。在这种情况下,它是avahi_service_resolver_new 的最后一个参数。这有帮助吗? @kaylum 我已经添加了代码,我尝试使用我对上下文指针如何工作的一点了解。我不知道我是否应该更改函数签名以适应输入。 【参考方案1】:

在更改 resolve_callback() 的函数签名时,我还应该在 PpDnsWindow *self 之前添加 AVAHI_GCC_UNUSED,如下所示。但这不是browse_callback()所必需的。

static void resolve_callback(
    AvahiServiceResolver *r,
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *address,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    AVAHI_GCC_UNUSED PpDnsWindow *self)

我在网上查了 AVAHI_GCC_UNUSED,但找不到任何实质性的东西。如果有人解释它的重要性,我将不胜感激。

【讨论】:

以上是关于如何将结构传递到browse_callback,然后进一步向下传递到avahi中的resolve_callback?的主要内容,如果未能解决你的问题,请参考以下文章

如何将结构数组从 c++ 传递到 c#?

如何将向量从 Cuda 直接传递到 LibSVM 结构?

如何将结构中的char *从c#传递到c++

如何将带有 unsigned char* 的结构从 C# 传递到 C++?

如何将结构从 C++ 应用程序传递到 C++ Win32 DLL?

如何将变量从 ViewController 类传递给其他结构?