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_t
MacOSX C コンパイラの 4 バイト (2 バイトではない) wchar_t のために使用しました。vbstochar
の内容を見るために を呼び出した後にブレークポイントを追加しましたがconvarg
、Excel から呼び出すと動作するようです。
これはうまくいきますが、私が理解していないことの1つはlen
、vbstrlen
関数内で2を掛ける必要がある理由です。私はCに慣れていないので、ポインタについて少し読む必要がありました. 2 バイト文字が含まれている場合、2 を掛けずに正しい文字列の長さを取得する必要がありますか? 誰かが私にこれを説明したり、チュートリアルへのリンクを投稿したりできれば素晴らしいと思いますか?
また、文字列引数を持つ関数は、VBA で呼び出されたときに機能しますが、最初の呼び出しの後でのみ機能します。BSTR*
そのため、最初に dylib から引数を指定して関数を呼び出すと(アプリケーション、この場合は Excel を起動した後)、BSTR*
ポインターは特定の (ランダムな?) アドレスを指すだけで、文字列は指しません。VBA から関数を 2 度目に呼び出すと、すべてが正常に機能します。