我正在尝试为Linux中的firebird创建一些简单的UDF(在使用GCC编译的C中)。 问题是,当我将“返回机制”设置为“通过引用”时,当我调用该函数时,服务器崩溃。 当它是“按价值”时,没有问题。
以下是我尝试用C编写的函数:
这个有效:
double round(double *);
double round(val)
double *val;
{
*val = *val * 100;
*val = (*val>= 0) ? (long)(*val + 0.5) : (long)(*val - 0.5);
*val = *val / 100;
return *val;
}
但是这个在调用时会崩溃服务器:
char * proper_case(str)
char * str;
{
return str;
}
以下是DDL:
DECLARE EXTERNAL FUNCTION "ROUND"
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'round' MODULE_NAME 'my_udfs.so';
DECLARE EXTERNAL FUNCTION PROPCASE
CSTRING(10000)
RETURNS CSTRING(10000) FREE_IT
ENTRY_POINT 'proper_case' MODULE_NAME 'my_udfs.so';
我用第二个函数调用:
select propcase('abrakadabra') from rdb$database;
firebird服务器崩溃,我收到的唯一错误信息是:
Statement failed, SQLSTATE = -902
Error reading data from the connection.
有人可以提供建议吗?任何帮助将不胜感激!
我忘记提供的唯一信息是我正在编译的文件.so文件(可能是关键在这里):
gcc -c -O -fpic my_udf.c
ld -G my_udf.o -lm -lc -o my_udf.so
cp my_udf.so /usr/lib/firebird/2.1/UDF/my_udfs.so
答案 0 :(得分:2)
AFAIK,Firebird会在调用后尝试释放参数和返回值(因为它不知道你在函数中做了什么,并且你已经将你的返回值声明为FREE_IT
),所以你需要在返回之前为返回值分配空间。你必须用ib_util_malloc()
调用来分配内存,所以它看起来像(甚至没有尝试编译它,但它应该给你一般的想法):
char * proper_case(str)
char * str;
{
char* ret = (char*)ib_util_malloc(strlen(str) + 1);
strcpy(ret, str); // or run the actual logic here
return ret;
}
编辑:我在UDF lib中构建了一个Firebird示例:
pChar EXPORT IB_UDF_lower(const char *s)
{
if (!s) return 0;
char* buf = (char *) ib_util_malloc(strlen(s) + 1);
char* p = buf;
while (*s) {
if (*s >= 'A' && *s <= 'Z') {
*p++ = *s++ - 'A' + 'a';
}
else
*p++ = *s++;
}
*p = '\0';
return buf;
}
答案 1 :(得分:0)
这不是答案,而是我如何设法解决问题。
我正在使用以下命令编译UDF:
gcc -c -O -fpic my_udf.c
ld -G my_udf.o -lm -lc -o my_udf.so
cp my_udf.so /usr/lib/firebird/2.1/UDF/my_udfs.so
没有错误,firebird服务器崩溃也没有错误状态。 所以我打开了Python并尝试了以下内容:
from ctypes import *
libc = CDLL("path/to/my_udf.so")
libc.IB_UDF_lower("abrakadabra")
Python抛出有关非现有函数“ib_util_malloc”的错误。 所以我用“malloc”替换它,一切正常。
我仍然不知道我做错了什么,但由于GCC没有给我任何错误,我认为这是一个链接问题。