Click here to visit our sponsor

ActiveX DLL コンポーネント


ここは...

ここでは、ActiveX DLL について、思った事を記しています。
(コンポーネント作成側)


目次


登録情報

CLSID と IID自動生成 (ただし生成タイミングが [バージョン間の互換性] により違う)
ProgIDプロジェクト名 + ピリオド + クラス名
CoClass名クラス名 (レジストリの説明は ProgID と同じ)
タイプライブラリ名プロジェクト名 (レジストリの説明は [プロジェクトの説明])
インターフェイス名クラス名の先頭にアンダーバーを付けたもの

スレッドモデル

ActiveX DLL のスレッドモデルは2つ選択出来きます。
(ActiveX EXE は別です)

VB での呼び方COM での呼び方
アパートメント スレッドSTA
シングル スレッドプライマリSTA / 第1STA

どちらも、シングルスレッドです。
通常は、アパートメントスレッド の方を使います。

(STA は Windows95 から、プライマリSTA は、それ以前、つまりスレッドが無かった OLE 時代のもの)


標準モジュールのグローバル変数は、スレッド(アパートメント)ごとに独立しています。
同スレッドの異なるインスタンス間では共有されます。
プロセス間での共有ではありません。
(クライアントが MTA の場合、ちと厄介)

プロセス間にすると、同期処理が必要になり、VB の範疇では無いとの判断でしょう。
アパートメント間なら、スレッド間マーシャリングで同期がとれるし。


このグローバル変数の初期化が必要な時は、Sub Main で行います。
Sub Main は、1つのアパートメントで、
最初のインスタンスが作成された時に、1度だけ呼ばれます。

マルチスレッドのテストクライアントとして、IE/HTA を使うのが手軽です。


エラーの発行

以下のように、試験的にエラーを発生させて見ます。

Err.Raise &H8007000E

クライアントが VB の場合の結果は、

実行時エラー '7':
メモリが不足しています。

になりました。 (&H8007000E → 7)

ただし VB 以外のクライアントが受け取るのエラーコードは &H800A0007 です。

このことは、VB で作成したコンポーネントでは、
COMの標準的なエラーの発行が出来ない事を意味します。(一部のみ)


Err.Raise 1

のクライアント(VB以外)が受け取るエラーコードは &H800A0001 でした。
未定義のエラーは &H800A0000 が付加されるようです。

ただ、これは試験的に行ったのものですので、
実際には未定義エラーは使用せず、カスタムエラーを使います。


カスタムエラーの番号は
 (512〜65535) + vbObjectError(&H80040000)
の範囲です。
(&H80040200〜&H8004FFFF)

エラーについては資料ページをどうぞ。
(資料ページ) HRESULT


タイプライブラリの生成 (IDL)

VB がどのようなタイプライブラリを生成するのか調べてみました。
(資料ページ) テータ型

Function, Sub と ByVal, ByRef

クライアントの制限

VBScript, JScript のスクリプト環境では、参照渡し ByRef の変数を引数として使えません。

Sub プロシージャ
Public Sub SubMethod(ByRef arg As Integer)

  ↓ ↓

HRESULT SubMethod([in, out] short* arg);

Function プロシージャ
Public Function FunctionMethod(ByVal arg As Byte) As Single

  ↓ ↓

HRESULT FunctionMethod(
    [in] unsigned char arg,
    [out, retval] single* );

あれ、Single って float にならないのか...
(後述: OLE/COM Viewer の誤りだと思われます)


デフォルト引数
Public Sub DefOption(
    Optional ByVal bOption As Boolean = True)

  ↓ ↓

HRESULT DefOption(
    [in, optional, defaultvalue(-1)] VARIANT_BOOL bOption);

Let と Set の違い

put_LetProperty
Public Property Let LetProperty(ByVal vData As Variant)

  ↓ ↓

[propget] HRESULT LetProperty([in] VARIANT vData );

put_SetProperty
Public Property Set SetProperty(ByVal vData As Variant)

  ↓ ↓

[propputref] HRESULT SetProperty([in] VARIANT vDAta );

Set は参照だから、ref 。ふむふむ。

配列のプロパティは?

get_typeArray
Public Property Get typeArray() As type()

  ↓ ↓

[propget] HRESULT typeArray([out, retval] SAFEARRAY(type)* );

put_typeArray
Public Property Let typeArray(ByRef ary() As type)

  ↓ ↓

[propput] HRESULT typeArray([in, out] SAFEARRAY(type)* );

列挙型は Long

Public Enum typeEnum
    Large = &H7FFFFFFF
    Minus = &H80000000
End Enum

  ↓ ↓

typedef [
    uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),
    version(1.0)
]
enum
{
    Large = 2147483647,
    Minus = -2147483648
} typeEnum;

あれ、v1_enum 付いてない...


おわりに

このページの満足度は・・・

素晴らしい!
まあまあ、良いかも
自己満足感がよくわかるページですね
まったくもって説明不足


Visual Basicページトップ

HOME

兄弟ページ 姉妹ページ
Click here to visit our sponsor