1

MacOSX dylib から VBA から C コードが呼び出されたときに、VBA から渡された文字列を変換するための C でいくつかのコードを作成しました。ここでいくつかの良いヒントを得ました。私は ASCII 文字列しか気にしないのでBSTR、単純なに変換する次の関数を作成しましたchar*

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "myheader.h"

size_t vbstrlen(BSTR *vbstr)
{
    size_t len = 0U;
    while(*(vbstr++)) ++len;
    len = len*2;
    return len;
}

void vbstochr(BSTR *vbstr, char** out)
{
    int len2 = vbstrlen(vbstr);
    char str[len+1];

    int i;

    for(i = 0; i < len; i++)
    {
        str[i] = (char) (((uint16_t*) vbstr)[i]);
    }

    str[i] = '\0';

    asprintf(out, str);
}

int test(BSTR *arg1)
{
    char* convarg;
    vbstochr(arg1, &convarg);

    return 1;
}

myheader.h は次のようになります。

typedef uint16_t OLECHAR;
typedef OLECHAR * BSTR;

. uint16_tMacOSX C コンパイラの 4 バイト (2 バイトではない) wchar_t のために使用しました。vbstocharの内容を見るために を呼び出した後にブレークポイントを追加しましたがconvarg、Excel から呼び出すと動作するようです。

これはうまくいきますが、私が理解していないことの1つはlenvbstrlen関数内で2を掛ける必要がある理由です。私はCに慣れていないので、ポインタについて少し読む必要がありました. 2 バイト文字が含まれている場合、2 を掛けずに正しい文字列の長さを取得する必要がありますか? 誰かが私にこれを説明したり、チュートリアルへのリンクを投稿したりできれば素晴らしいと思いますか?

また、文字列引数を持つ関数は、VBA で呼び出されたときに機能しますが、最初の呼び出しの後でのみ機能します。BSTR*そのため、最初に dylib から引数を指定して関数を呼び出すと(アプリケーション、この場合は Excel を起動した後)、BSTR*ポインターは特定の (ランダムな?) アドレスを指すだけで、文字列は指しません。VBA から関数を 2 度目に呼び出すと、すべてが正常に機能します。

4

2 に答える 2

2

BSTR には長さが埋め込まれているため、手動で長さを計算する必要はありません。

長さを 2 倍にする必要があるのは、BSTR が 2 バイト文字を使用しているにもかかわらず、 char1 バイトしかないためです。文字数ではなく、BSTR のバイト数を返すように vbstrlen() 関数をコーディングしました。

ASCII 文字列のみに関心があるため、コードを次のように簡略化できます。

#include <stdlib.h> 
#include <stdio.h> 
#include <stdint.h> 
#include "myheader.h" 

size_t vbstrlen(BSTR *vbstr) 
{ 
    if (vbstr)
      return *(((uint32_t*)vbstr)-1);
    return 0; 
} 

void vbstochr(BSTR *vbstr, char** out) 
{ 
    size_t len = vbstrlen(vbstr); 
    char str[len+1] = {0};

    for(size_t i = 0; i < len; ++i) 
        str[i] = (char) vbstr[i]; 

    asprintf(out, str); 
} 
于 2012-04-10T01:39:53.837 に答える
0

VB 文字列は、1 文字あたり 2 バイトを使用する UTF-16 文字列である可能性があります (サロゲート ペアとしてエンコードされる BMP、基本多言語面、または U+0000..U+FFFF を超える文字を除く)。したがって、「ASCII」データの場合、ASCII 文字とゼロバイトが交互に表示されます。「2 を掛ける」というのは、UTF-16 がカウントされた各文字を格納するために 2 バイトを使用するためです。

これは、次のように見るとほぼ決定的です。

typedef uint16_t OLECHAR;
typedef OLECHAR * BSTR;
于 2012-04-10T01:31:12.107 に答える