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

时间:2018-12-17 05:59:58

标签: c++ mysql c

在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 *

2 个答案:

答案 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文档页面),则应使用resultlength参数“返回”您的字符串:

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个字节,则需要为它自己分配缓冲区,更重要的是取消分配它以避免内存泄漏。为了实现这一点,您将必须实现this 中所述的其他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];
}

您还可以按照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 *指向的内存。