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

ltskdhd1  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(417)

在mysql中编写udf时,我一直在从c调用一个c++函数,这个函数应该返回 char * . 我试过的是:
加密.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*;
}

自定义项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 * ?

kq4fsx7k

kq4fsx7k1#

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

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

那你应该用 result 以及 length 参数以“返回”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;
}

如果您的字符串不总是适合255字节,您需要自己为它分配缓冲区,更重要的是取消分配它以避免内存泄漏。要实现这一点,您必须实施额外的 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];
}

你也可以用 initid->ptr 对于字符串缓冲区本身,这里建议使用 malloc/realloc/free 组合,但我认为最好用 struct 甚至是一个 class 在多个函数之间共享公共上下文的通用模式。
还要注意的是 encrypt 函数可以多次调用(对于每行)并且 encrypt_deinit 将只调用一次(对于每个sql语句),因此必须取消分配或重用中的前一个缓冲区 encrypt 在分配新的之前。

rdlzhqv9

rdlzhqv92#

一般来说,要从c++字符串返回char*,可以执行以下操作:

char *c = (char*)malloc(str.size() + 1);
strcpy(c, str.c_str());
return c;

请注意,调用者必须释放char*指向的内存。

相关问题