从C调用C++函数返回char*

Amo*_*ogh 0 c c++ mysql

在MySQL中编写UDF时,我很难从c调用c ++函数,而c函数应该返回char *.我试过的是:

encrypt.cpp

string encrypt(string Data)
{
   ...
   //some encryption logic
   ...
   return encryptStr; //encryptStr is string 
}
Run Code Online (Sandbox Code Playgroud)

要从c调用上面的函数,我extern c在同一个文件中使用:

extern "C" char * c_encrypt(char *bar)
{
    std::string str = encrypt(std::string(bar));
    return what_to_do_to_return_char*;
}
Run Code Online (Sandbox Code Playgroud)

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 ;
}
Run Code Online (Sandbox Code Playgroud)

那么,我该怎么做c_encrypt()才能回来char *

r3m*_*n0x 5

根据MySQL文档,您的函数应该具有以下原型:

extern "C" char *encrypt(UDF_INIT *initid, UDF_ARGS *args,
      char *result, unsigned long *length,
      char *is_null, char *error);
Run Code Online (Sandbox Code Playgroud)

然后你应该使用resultlength参数"返回"你的字符串,如果它适合255个字节(根据文档页面):

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;
}
Run Code Online (Sandbox Code Playgroud)


如果你的字符串并不总是适合255个字节,你需要自己为它分配缓冲区,更重要的是解除分配它以避免内存泄漏.要实现此目的,您必须实现此处所述的其他功能encrypt_initencrypt_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];
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用组合使用此处initid->ptr建议的字符串缓冲区本身,但我认为使用或甚至作为一般模式在多个函数之间共享公共上下文总是更好.malloc/realloc/freestructclass

还要注意的是,encrypt函数可以调用多次(每行)和encrypt_deinit将只调用一次(对每个SQL语句),所以你必须取消分配或重新使用以前的缓存encrypt分配一个新的人之前.