「"」で囲まれた中にある「,」は無視するなど
VB標準のSplit関数では物足りない部分を補うために
Public Function CsvSplit(ByVal iStr As String) As String()
のような形式でSplit関数とほぼ同じインターフェースを持つ
オリジナル関数を作ってみたのですが
処理速度向上のために(実際に速度があがるかどうかわかりませんが)
VC++でDLLを作ってみようと考えています。
そこでここの掲示板の過去ログやGoogle等で
VBから呼び出すためのDLLの作り方を色々探してみたところ、
引数としてVB側であらかじめ領域を確保した文字列変数を渡して
そこに結果を格納する方法などは見かけるのですが
「戻り値として文字列配列を返す」サンプルを見つけることができませんでした。
ということでお聞きしたいのは主に次の3点です。
・そもそも可能ですか?(^^;
・DLLソースでの関数宣言とVB側のDeclareはどのような形になりますか?
・文字列配列を返すとなるとメモリ確保/解放の仕組みはどうなりますか?
なるべくSplit関数に近い形にしたいと思うので
例えば引数に空文字列("")を受け取って返した結果を
VB側のLBound/Uboundでチェックすると0/-1になるのが理想ですが…
環境はVC++とVB6(SP6)、WindowsXPを想定しています。
以上、よろしくお願いいたします。
> そもそも可能ですか?(^^;
可能です。
> 文字列配列を返すとなるとメモリ確保/解放の仕組みはどうなりますか?
GlobalAlloc等のAPIを使います。
文字列配列を返すときは、SAFEARRAYオブジェクトを使います。
とりあえず、「SAFEARRAY」をキーワードに検索してみてください。
> 可能です。
断定しないほうがよさそう。
ByRefで配列をVariant変数を渡す方法は
http://support.microsoft.com/default.aspx?scid=kb;ja;410837#XSLTH3161121122120121120120
String 型の配列の引き渡しの サンプル
にあります。
Splitとは違う使われ方になると思うけど結構簡単にできそう。
Public Sub CsvSplit(ByRef oData, ByVal iStr As String)
見たいな感じで。
# どうしてもSplitのような形式にしたいならば、VBでDLL側との連携するラッパー関数を作ればいいと。
Splitの構文は、ODLで記すと、
VARIANT __stdcall Split
( [in] BSTR Expression,
[in, optional] VARIANT* Delimiter,
[in, optional, defaultvalue(-1)] long Limit,
[in, optional, defaultvalue(0), "1")] bCompareMethod Compare);
なのですから、それを参考にしてみるとか。もっともODL/IDLで記述
するのであれば、
HRESULT __stdcall Split
( [in] BSTR Expression,
[in, optional] VARIANT* Delimiter,
[in, optional, defaultvalue(-1)] long Limit,
[in, optional, defaultvalue(0), "1")] bCompareMethod Compare,
[out, retval] VARIANT* pvarResult);
もしくは、
HRESULT __stdcall Split
( [in] BSTR Expression,
[in, optional] VARIANT* Delimiter,
[in, optional, defaultvalue(-1)] long Limit,
[in, optional, defaultvalue(0), "1")] bCompareMethod Compare,
[out, retval] SAFEARRAY(BSTR)** psaResult);
のような構文にするのが無難かと。
タイプライブラリが作れない、という場合は、素直に戻り値を
VARIANTにするべきでしょう。Declareステートメントを用いる
と、文字列型そのものもしくはその配列を引数もしくは戻り値
として使う際には、VBによりAnsi<=>Unicodeの変換が行われて
しまうからです。
COMベースで考えればよかったですね。
(といか、私はCOMはつくったことないですけど。)
適当につくってみたら
Private Declare Function SetStrArray Lib "xxx.dll" () As String()
__declspec( dllexport ) LPSAFEARRAY __stdcall SetStrArrayEx()
見たいなのはできました。(上手くいっているように見えるだけかも)
> VBによりAnsi<=>Unicodeの変換が行われて
これかなりうざったいですね。SysAllocStringByteLenなのかSysAllocStringなのか
よくわからなくなる。
まぁ、Declareするのならば、VARIANTで包むのが楽でしょうね。
SAFEARRAY*そのままに拘る必要はないと思いますよ。
たくさんのご回答ありがとうございます。
SAFEARRAY等のキーワードがまだ消化し切れていないので
ちょっと試行錯誤してみようと思います。
| ツイート |
|