Для первой части вопроса математические операции, такие как sinf
, должны обрабатываться стандартной библиотекой C (вам следует проверить конкретную версию на предмет поддержки вашей архитектуры).Затем вы можете использовать заголовок math.h
и его функции, компилятор должен затем использовать FPU для выполнения вычислений с плавающей запятой.
Для второй части - обычный способ показать пользователю скрытыйструктура с декларацией foward , но пользователю придется взаимодействовать со структурой с помощью указателей и функций доступа.
В качестве примера, скажем, у нас есть четыре файла:
api.h
: открытый заголовок api.c
: исходный код для функций из открытого заголовка foo.h
: внутренний заголовок библиотеки (не будет доставлен конечному пользователю) foo.c
: исходный код для внутренних функций
api.h
- единственный интересный файл из них (без изменений).
// file: api.h
#ifndef API_H
#define API_H
struct foo; // forward declaration of the foo structure
typedef void (*callback_t)(struct foo*); // typedef for a callback taking a
// struct foo argument
void set_callback(callback_t fn);
#endif
Теперь у нас есть тип для обратного вызова и тип структуры, заданной для обратного вызова, но пользователь не может взаимодействовать с самой структурой, поскольку компилятор только знает, что она существует, но не знает ее содержимого (и размера хранилища)..
Когда пользователь пишет обратный вызов, как показано в приведенном ниже коде, ему понадобятся некоторые функции доступа.
#include "api.h"
void user_callback(struct foo* arg) {
// user code here
}
Функции доступа обычно определяются следующим образом:
// in the file api.h or another header that the user has access to
int foo_get_value1(struct foo* arg);
void foo_set_value1(struct foo* arg, int new_value);
и эти функции будут реализованы в foo.c
struct foo {
int value1;
int value2;
};
int foo_get_value1(struct foo* arg) {
return arg->value1;
}
void foo_set_value1(struct foo* arg, int new_value) {
arg->value1 = new_value;
}
Этот подход имеет дополнительное преимущество, заключающееся в том, что ваши foo_set
функции могут выполнять проверки достоверности, чтобы убедиться, что у вас есть соответствующие значения вструктура.
Обратите внимание: Я не добавил никаких проверок в свои функции доступа, чтобы избежать загромождения кода, но при передаче указателя на функцию всегда следует проверять его на * 1047.*