我有一个使用int类型的共享(或静态)库的C api,并希望升级到int64_t。 这样做,我想确保我以前的用户仍然可以升级库,而不必重写他们的整个代码。
我已经提出了这个要点的解决方案,它复制了我的代码行为(使用回调):https://git.io/vMy8G -
// 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;
}
#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();
#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
(这将根据其他一些设置自动完成)。最新的定义将确保向后兼容性。
Valgrind检查通过所有构建。
我的问题如下:
请注意,如果可能,我想避免编写所有函数的64位版本。此外,这必须适用于Linux(gcc),Mac(gcc)和Windows(Visual Studio)。
答案 0 :(得分:0)
编写最佳移植代码的最佳方法是不依赖于大小。如果您明确使用uint32_t
或int64_t
。
否则使用原生int
或long
。
请求用户为完全不必要的东西定义宏是容易出错和错误的。
答案 1 :(得分:0)
没有。 example.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)。代码调用具有一个签名的函数,但该函数可能具有不兼容的函数。
是。
答:当然不要使用不匹配的功能签名进行编码
B.最后,我认为OP需要一种新的方法。我建议添加一项功能define_callback64()
,然后让用户像以前一样使用define_callback64()
或int (*f)(const int, int64_t, const int)
致电define_callback()
。然后call_callback()
可以使用已设置的那个。
代码评论
OP希望"想要升级到int64_t"但是"避免编写所有函数的64位版本"。这是最奇怪的,显然是矛盾的。请注意,如果可能,我想避免编写所有函数的64位版本。
也许将internal.c
重写为int64_t
,然后调用select call back函数。
const
中的3 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
而且#34;库总是用#define MYLONG int64_t
"编译。 OP需要在代码和文档中正确且一致地使用类型。