寻找最短的字符串类型转换C ++

时间:2012-09-07 19:23:23

标签: c++ string pointers com bstr

我正在制作一个使用C#托管DLL的非托管C ++ DLL。我正在编写C ++库,因为我需要使用软件中定义的函数和头文件,C ++库可以作为插件添加。但是我想要做的事情是如此复杂,以至于我对C ++的稀疏知识会让我失望,所以我决定用我最喜欢的C#做事并通过COM连接DLL并且我成功了。

我在使代码工作方面有所成功,但在保持代码简洁方面不太成功,因为我显然不是专业的C ++程序员。

问题在于转换各种字符串类型。特别是BSTR和const char *。

以下代码将const char *转换为BSTR:

BSTR bstrt;
const char * someChar;

csharpInterfacedClassPointer->get_PropertyForSomeChars(&bstrt);
strcpy_s(nstring, (char *)bstrt);
someChar = nstring;

问题是,我有很多离散的someChars和相应的离散接口方法......属性方法是从C#接口生成的,所以我不能改变它。每个“someChar”都需要以下三行代码,因此对于30个离散变量,我需要编写90行代码。

csharpInterfacedClassPointer->get_PropertyForSomeCharX(&bstrt);
strcpy_s(nstring, (char *)bstrt);
someCharX = nstring;

问题是:如何为此写一些快捷方式,以便它只适合一行?

我尝试了一些带有“getter”函数指针和someChar指针的函数。

typedef HRESULT (__stdcall *get_string_func)(BSTR * str); //getter function pointer

//the converting function
void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
{
const size_t nsize = 1000;
char nstring[nsize];

BSTR bstrt;
bstrt = bstr_t(constCharString);
bstr_get_fx(&bstrt);
strcpy_s(nstring, (char *)bstrt);
constCharString = nstring;
}

//calling the function...as I thought that would work
ConvertAndAssign(sPtr->get_DataFile, someChar);

然后编译器说了一些奇怪的事情,但是它们是如何绑定函数的,以及它们不被允许作为指针...我用Google搜索它的意思和改变函数定义所需的解决方案但我不能这样做,因为定义是从C#代码生成的(通过regasm.exe)。

重要提示:我最终需要获取const char *类型,因为它是我正在制作C ++ DLL的程序函数所需的输入类型。

2 个答案:

答案 0 :(得分:1)

Disclaimer: it was a long time (7 years to be more precise) since I have touched C++/COM code for the last time.

关于将实例方法绑定到函数指针,请检查此SO问题。

另一种选择是使用IDispatch接口(如果你的COM组件实现它)

关于ConvertAndAssign()实现,IMO有一些问题。为了便于解释,我将其复制下面:

void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
{
    const size_t nsize = 1000;
    char nstring[nsize];

    BSTR bstrt;
    bstrt = bstr_t(constCharString); // issue 1
    bstr_get_fx(&bstrt);
    strcpy_s(nstring, (char *)bstrt); // issue 2
    constCharString = nstring; // issues  3 & 4
} 
  1. 如果你的COM方法返回一个BSTR(即它有一个BSTR类型的out参数)你不应该传递一个预先分配的字符串,否则你最终会 泄露记忆。

  2. bstr 投射到char *将无效。 BSTR是Unicode字符串。它们也被编码为其长度优先于实际字符。 如果您使用的是ATL / MFC,则可以使用string conversion macros之一。 如果您不使用ATL / MFC,您可以使用WideCharToMultiByte()函数或其中一个“智能”BSTR类(ATL中的CComBSTR,bstr_t等)

  3. nstring 分配给 constCharString 不会对外部字符串产生影响。如果您正在调用ConvertAndAssign,如下所示

    char *outsideStr = NULL;              
    ConvertAndAssign(whatever, outsideStr);
    

    在ConvertAndAssign()函数内部 consCharString 将在开头指向NULL。分配后, constCharString 确实指向 nstring 但是 outsideStr 仍然指向NULL(记住,当你调用ConvertAndAssign()函数时,指针值的副本被传递给它)。

    为了得到你想要的东西,你可以传递一个引用或一个指向指针的指针:

     void ConvertAndAssign(get_string_func bstr_get_fx, const char * &constCharString) 
     {
          constCharString = nstring; // Assignment
     }   
    

    或指向指针的指针:

     char *outsideStr = NULL;
     ConvertAndAssign(whatever, &outsideStr);
    
     void ConvertAndAssign(get_string_func bstr_get_fx, const char **constCharString) 
     {
          .
          .
          .
          *constCharString = nstring; // Assignment
     }
    
  4. 修复上一个问题后,你会遇到另一个问题:你无法返回局部变量的地址!当ConvertAndAssign()返回后,您的代码恢复,这个 地址不再为你分配(它是堆栈的一部分,所以它甚至可能看起来有效,但我向你保证,它不是;最轻微的变化 在你的代码中可能会破坏它)

    要解决此问题,您需要传递预先分配的字符串:

    char outsideStr[1000];
    ConvertAndAssign(whatever, outsideStr);
    
    void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
    {
        strcpy_s(constCharString, /* result str here */ );
    }
    

    或在堆中分配一个字符串。

  5. 鉴于上述所有内容,ConvertAndAssign()及其用法的一种可能实现如下:

    char outsideStr[1000];
    ConvertAndAssign(whatever, outsideStr);
    
    void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
    {
        BSTR bstrt;
        if(SUCCEEDED(bstr_get_fx(&bstrt)))
        {
             // Assumes constCharString points to a buffer large enough to hold the converted string.
            strcpy_s(constCharString, CW2A(bstr)); // not completely correct since bstr may contain the byte 0 but I guess thats not your scenario.
            SysFreeString(bstr);
        }
        else
        {
             // error handling.
             constCharString[0] = 0;
        }
    }
    

答案 1 :(得分:0)

如果有任何mod要阅读此内容,可以删除此问题。我意识到我有一个完全不同的问题。感谢Vagaus的努力。