我正在尝试包装libcups库https://github.com/apple/cups以在我的Swift项目中使用。
我已经尝试了https://www.cups.org/doc/cupspm.html中的一些示例,但它们运行正常。
但是在包装要在Swift项目中使用的C代码时,我很挣扎。
我一直在网上搜索如何在Swift中包装C库,但进展不大。
这是C代码
#include <stdio.h>
#include <cups/cups.h>
typedef struct {
int num_dests;
cups_dest_t *dests;
} my_user_data_t;
int my_dest_cb(my_user_data_t *user_data, unsigned flags, cups_dest_t *dest) {
if (flags & CUPS_DEST_FLAGS_REMOVED) {
user_data->num_dests = cupsRemoveDest(dest->name, dest->instance, user_data->num_dests, &(user_data->dests));
} else {
user_data->num_dests = cupsCopyDest(dest, user_data->num_dests, &(user_data->dests));
}
return 1;
}
int my_get_dests(cups_ptype_t type, cups_ptype_t mask, cups_dest_t **dests) {
my_user_data_t user_data = { 0, NULL };
if (!cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, type, mask, (cups_dest_cb_t)my_dest_cb, &user_data)) {
cupsFreeDests(user_data.num_dests, user_data.dests);
*dests = NULL;
return 0;
} else {
*dests = user_data.dests;
return user_data.num_dests;
}
}
int main(int argc, const char * argv[]) {
cups_dest_t *dests = NULL;
int num_dests = my_get_dests(0, 0, &dests);
printf("Destination found: %d\n", num_dests);
cups_dest_t *dest;
int i;
const char *value;
for (i = num_dests, dest = dests; i > 0; i--, dest++) {
if (dest->instance == NULL) {
value = cupsGetOption("printer-info", dest->num_options, dest->options);
printf("%s (%s)\n", dest->name, value ? value : "No description");
}
}
return 0;
}
这里是同一件事,但在Swift中
let destinationsCallback: cups_dest_cb_t = { user_data, flags, dest in
// (void *user_data, unsigned flags, cups_dest_t *dest)
var userDataPointer = user_data!.assumingMemoryBound(to: my_user_data_t.self).pointee
var destData = dest!.pointee
if destData.instance != nil {
print("\(String(cString: destData.name))/\(String(cString: destData.instance))")
} else {
print(String(cString: destData.name))
}
if flags == CUPS_DEST_FLAGS_REMOVED {
userDataPointer.num_dests = cupsRemoveDest(destData.name, destData.instance, userDataPointer.num_dests, &(userDataPointer.dests))
} else {
userDataPointer.num_dests = cupsCopyDest(dest, userDataPointer.num_dests, &(userDataPointer.dests))
}
return 1
}
func getDestinations(type: UInt32, mask: UInt32, dests: UnsafeMutablePointer<cups_dest_t>) -> Int32 {
var userData = my_user_data_t(num_dests: 0, dests: nil)
if cupsEnumDests(UInt32(CUPS_DEST_FLAGS_NONE), 1000, nil, type, mask, destinationsCallback, &userData) != 1 {
return 0
} else {
return userData.num_dests
}
}
我无法获得userData以返回正确的值,我认为这是由于我处理指针的方式。
非常感谢,如果我能得到一些建议。
我已经用C编写了所有的库访问函数,然后从我的快速代码中调用这些 C函数。这是因为我已经有杯子从以前的项目访问代码,并且不需要更改。
这很容易做到,互联网上有足够的例子说明如何做到这一点-从swift快速调用c函数-包括传递返回值。
很抱歉,但这是几个月前的事情,所以我无法提供更多详细信息。但是您肯定会在这里和互联网上找到示例。
希望有帮助,罗伯特
恕我直言,在Swift中使用此类C库的最佳方法是在Objective-C中使用它们。尽管如此,主要的问题似乎是您没有将对用户数据的更改写回,这就是为什么您总是得到初始值的原因。您需要像这样在回调中对其进行更新
let userDataPointer = user_data!.assumingMemoryBound(to: my_user_data_t.self)
var userData = userDataPointer.pointee
...
// make some changes to userData
userDataPointer.pointee = userData
return 1
而且您的C代码和Swift代码之间似乎也有一些区别,例如使用'flags == CUPS_DEST_FLAGS_REMOVED'检查标志,通常这是错误的检查标志的方式,并且将cupsEnumDests的结果与1进行比较您检查结果是否为0的原始代码。