В Ubuntu 14.04, я написал C файл под названием hash.c:Python ctypes: OSError неопределенный символ при загрузке библиотеки
/* hash.c: hash table with linear probing */
typedef struct {
void *key;
void *value;
} ht_entry;
typedef struct {
ht_entry *table;
int len;
int num_entries;
int (*hash_fn)(void *key);
int (*key_cmp)(void *k1, void *k2);
} hashtable;
и скомпилирован с
gcc -shared hash.c -o test.so -fPIC
После этого я попытался загрузить test.so в скрипте Python (для тестирования), но я получил следующую ошибку: «OSError: .../test.so: undefined symbol: hash_fn»
hash_fn - это указатель на функцию в структуре hashtable. Он ссылается несколько раз на функции позже в файле.
Я не понимаю, почему эта ошибка происходит. У меня есть Googled, но все остальные случаи относятся либо к C++, либо к ним. В моем случае у меня есть только 1 файл C, который включает только stdio и stdlib.
вот код FULL. Когда я комментирую все, кроме hash_create и print_info, он загружается успешно. Когда я раскомментирую find(), это ошибка. (print_info только для тестирования, что ctypes работы)
/* hash.c: hash table with linear probing */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *key;
void *value;
} ht_entry;
typedef struct {
ht_entry *table;
int len;
int num_entries;
int (*hash_fn)(void *key);
int (*key_cmp)(void *k1, void *k2);
} hashtable;
static void close_gap(hashtable *ht, int i);
static int find(hashtable *ht, void *key);
hashtable* hash_create(int len, int (*hash_fn)(void*), int (*key_cmp)(void*, void*))
{
hashtable* ht = (hashtable*) malloc(sizeof(hashtable));
ht->len = len;
ht->table = calloc(len, sizeof(ht_entry));
ht->hash_fn = hash_fn;
ht->key_cmp = key_cmp;
ht->table[0].key = 2;
ht->table[0].value = 3;
return ht;
}
void print_info(hashtable *ht)
{
printf("%d, %d, %d\n", ht->len, ht->table[0].key, ht->table[0].value);
}
void* hash_retrieve(hashtable* ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return NULL;
}
return ht->table[i].value;
}
void hash_insert(hashtable* ht, void *key, void *value)
{
if(ht->num_entries == ht->len) {
return;
}
int i = hash_fn(key) % ht->len;
while(ht->table[i].key != NULL) {
i = (i + i) % ht->len;
}
ht->table[i].key = key;
ht->table[i].value = value;
}
void hash_remove(hashtable *ht, void *key)
{
int i = find(ht, key);
if(i < 0) {
return;
}
ht->table[i].key = 0;
ht->table[i].value = 0;
close_gap(ht, i);
}
static int find(hashtable *ht, void *key)
{
int i = hash_fn(key) % ht->len;
int num_checked = 0;
while(ht->table[i].key && num_checked != ht->len) {
if(!ht->key_cmp(ht->table[i].key, key)) {
return i;
}
num_checked++;
i = (i + i) % ht->len;
}
return -1;
}
static void close_gap(hashtable *ht, int i)
{
int j = (i + 1) % ht->len;
while(ht->table[j].key) {
int loc = ht->hash_fn(ht->table[j].key);
if((j > i && (loc <= i || loc > j)) || (j < i && (loc <= i && loc > j))) {
ht->table[i] = ht->table[j];
ht->table[j].key = 0;
ht->table[j].value = 0;
close_gap(ht, j);
return;
}
}
}
Похоже, что 'hash_fn' будет глобальной функцией. Имена членов структуры не компилируются в качестве символов в исполняемый файл. –
Нам действительно нужно увидеть строку кода, из которой исходит ошибка. Где и как вы называете 'hash_fn'? – cdarke
@cdarke Готово. См. OP. – user1299784