我有一个使用int类型的共享(或静态)库的C api,并且希望升级到int64_t。这样做,我想确保我以前的用户仍然可以升级这个库,并且不需要重写他们的全部代码。
我已经在这个gist上找到了一个解决方案,它复制了我的代码行为(使用回调):https://git.io/vMy8G -
example.c
// User defines a different type
#define MYLONG int
#include "interface.h"
#include "stdio.h"
// User callback using his own type
int test(const int i, const my_long var, const int j) {
printf("i = %d\n",i);
printf("var = %lld\n",(long long) var);
printf("j = %d\n",j);
printf("%lld\n", 2LL*var-11);
return var - 7;
}
int main() {
// This is what user sees
api_func functionPtr = &test;
define_callback(functionPtr);
// Simulate callback call
call_callback();
return 0;
}interface.h
#pragma once
// MYLONG is defined differently internally and externally (before importing this file)
typedef MYLONG my_long;
// Callback definition
typedef int (*api_func)(const int, const my_long, const int); // surround by int to test alignment issues
void define_callback(api_func fptr);
void call_callback();internal.c
#define MYLONG long long
#include "interface.h"
// Callback handling
api_func callback_ptr = 0;
void define_callback(api_func fptr) {
callback_ptr = fptr;
}
void call_callback() {
(*callback_ptr)(1000, 100000, 100);
(*callback_ptr)(1000, 10000000000, 100); // will overflow when user uses int
}库将始终使用#define MYLONG int64_t编译,而用户将使用#define MYLONG int64_t或#define MYLONG int (这将根据其他设置自动完成)。最新的定义将确保向后兼容。
所有的建筑都通过了瓦伦的检查。
我的问题如下:
请注意,如果可能的话,我希望避免编写所有函数的64位版本。此外,这还必须在Linux (gcc)、Mac (gcc)和Windows (Visual )上工作。
发布于 2017-01-25 14:51:02
不是的。C中的用户将callback_ptr设置为:
int test(const int i, const int var, const int j)..。call_callback()将其称为:
int (*api_func)(const int, const int64_t, const int)当int与int64_t的类型不同时,这就是UB (不溢出)。
是。
它是未定义的行为(UB)。代码调用一个带有一个签名的函数,但是该函数可能有一个不兼容的函数。
是。
当然不要用错误匹配的函数签名来编码.
最后,我认为OP需要一种新的方法。我建议添加一个函数define_callback64(),然后让用户像以前一样用int (*f)(const int, int64_t, const int)或define_callback()调用define_callback64()。然后,call_callback()可以使用设置的那个。
代码注释
请注意,如果可能的话,我希望避免编写所有函数的64位版本。
OP希望“希望升级到int64_t”,但“避免编写64位版本的所有函数”。这是最令人好奇的,而且显然是矛盾的。
也许将internal.c重写为int64_t,然后调用select回调函数。
3 const in typedef int (*api_func)(const int, const my_long, const int)没有任何用途。
OP似乎假定int是32位,给出了标题。最好是编写不假定这一点的代码。int至少有16位.OTOH,假设int并不比int64_t更宽,但即使这也不是C规范所定义的,我不认为有什么大问题。
OP似乎也假定long long是int64_t给定的代码#define MYLONG long long,但是“库总是用#define MYLONG int64_t编译的”。OP需要在代码和文档中正确和一致地使用类型。
发布于 2017-01-19 19:41:45
要编写最好的移植代码,最好的方法就是不要依赖于大小。如果您确实显式地使用了uint32_t或int64_t。
否则使用本机int或long。
请求用户为完全不必要的东西定义宏是容易出错的。
https://stackoverflow.com/questions/41750235
复制相似问题