【发布时间】:2017-01-19 19:37:52
【问题描述】:
我有一个使用 int 类型的共享(或静态)库的 C api,并希望升级到 int64_t。 这样做,我想确保我以前的用户仍然可以升级库,而不必重写他们的整个代码。
我已经提出了关于这个要点的解决方案,它复制了我的代码行为(使用回调):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(这将根据其他一些设置自动完成)。最新的定义将确保向后兼容。
Valgrind 检查通过所有构建。
我的问题如下:
- 安全吗?
- 我是否依赖编译器的任何非保证行为?
- 为什么它会(或不会)起作用? (规范中有关于这方面的任何段落吗?)
- 您有什么更好的方法吗?
请注意,如果可能,我希望避免编写所有函数的 64 位版本。此外,这必须适用于 Linux (gcc)、Mac (gcc) 和 Windows (Visual Studio)。
【问题讨论】:
-
编辑:我已经简化了这个问题。另请注意,此处的宏定义是为了提供一个简单的最小示例。这不会暴露给最终用户。
-
你是对的。感谢您改进这篇文章。