在MySQL中编写UDF时,我被困在从c调用c ++函数,该函数应该返回char *
。我尝试过的是:
encrypt.cpp
string encrypt(string Data)
{
...
//some encryption logic
...
return encryptStr; //encryptStr is string
}
要从c调用上述函数,我在与以下文件相同的文件中使用extern c
:
extern "C" char * c_encrypt(char *bar)
{
std::string str = encrypt(std::string(bar));
return what_to_do_to_return_char*;
}
UDF.c
char* Encrypt_UDF( UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error )
{
const char* arg = args->args[0];
char * encryptData = c_encryt(arg); //calling c_encrypt()
return encryptData ;
}
那么,在c_encrypt()
中我该怎么做才能返回char *
?
答案 0 :(得分:5)
根据@Transactional,您的函数应具有以下原型:
extern "C" char *encrypt(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error);
然后,如果字符串可以容纳255个字节(根据MySQL documentation文档页面),则应使用result
和length
参数“返回”您的字符串:
extern "C" char *encrypt(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error)
{
std::string str = encrypt_impl(args->args[0]);
strcpy(result, str.c_str());
*length = str.size();
return result;
}
encrypt_init
和encrypt_deinit
函数,并定义一个数据结构,您将使用该数据结构在所有三个函数之间共享资源:>
struct EncryptData
{
std::string encryptedStr;
};
extern "C" bool encrypt_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
/* Use non-throwing allocation because there is no one to catch the exception */
initid->ptr = (char *) new (std::nothrow) EncryptData();
/* Return false if allocation failed */
if (!initid->ptr)
return false;
return true;
}
extern "C" void encrypt_deinit(UDF_INIT *initid)
{
delete (EncryptData *) initid->ptr;
}
extern "C" char *encrypt(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error)
{
EncryptData *data = (EncryptData *) initid->ptr;
data->encryptedStr = encrypt_impl(args->args[0]);
/* Can't return c_str() here, since the return type is non-const */
return &data->encryptedStr[0];
}
您还可以按照here的建议使用initid->ptr
组合使用malloc/realloc/free
作为字符串缓冲区本身,但是我认为最好使用struct
甚至是{ {1}}作为在多个功能之间共享通用上下文的通用模式。
还要注意,class
函数可以被调用多次(针对每一行),encrypt
仅被调用一次(针对每个SQL语句),因此您必须取消分配或在分配新缓冲区之前,请重用encrypt_deinit
中的先前缓冲区。
答案 1 :(得分:1)
通常要从C ++字符串返回char *,您可以这样做:
char *c = (char*)malloc(str.size() + 1);
strcpy(c, str.c_str());
return c;
请注意,调用方必须释放char *指向的内存。