器具/実施するing a C++ - UNO 橋(渡しをする) |
|
Contents
客観的な
Terminology
負担ing a 橋(渡しをする)
環境
Mapping
Microsoft Visual C++ - UNO 橋(渡しをする)
客観的な
This 文書 is written for developers 器具/実施するing a 橋(渡しをする) from C++ to binary UNO. The last paragraph covers the Microsoft Visual C++ - UNO 橋(渡しをする) in 詳細(に述べる).
Terminology
- 環境
An 環境 is 明確な/細部 to a programming language/ the compiler in which interfaces are 器具/実施するd, e.g. the 指名する "msci" for a C++ 環境 using the Microsoft Visual C++ compiler. It can also be 開会/開廷/会期 明確な/細部 for some 推論する/理由s, e.g. when running 多重の JVM (Java 事実上の machines) in one 過程.
- Mapping
A mapping is the directed way to publish an interface into another 環境, i.e. you 地図/計画する an interface from a source 環境 to a 的 環境. So you can invoke methods on a mapped interface (relating to the 的 環境) which are 委任する/代表d to the 起こる/始まるing interface in the source 環境. The 代表/ invocation is 成し遂げるd by the 橋(渡しをする). A mapped interface is called a proxy.
- 橋(渡しをする)
A 橋(渡しをする) denotes the 組織/基盤/下部構造 to 交流 interfaces between two 環境s and is bidirectional, supporting a mapping for each direction.
Example: The language binding Visual C++/UNO supports two mappings to 交流 interfaces from the 環境 "Visual C++" to the UNO 環境 and 副/悪徳行為 versa.
負担ing a 橋(渡しをする)
Each 橋(渡しをする) is 器具/実施するd in a separate 株d library 負担d by the UNO runtime. The 指名するing 計画/陰謀 of the library is a concatenation with the に引き続いて:
[purpose_]SourceEnvName_DestEnvName
The optional 目的 denotes the 目的 of the 橋(渡しをする), e.g. 議定書 traffic between two 環境s. If no 目的 is given, then the 橋(渡しをする) just 地図/計画するs interfaces from source to 目的地 環境.
Windows examples: prot_uno_uno.dll, msci_uno.dll
Solaris examples: libprot_uno_uno.so, libsunpro5_uno.so
The 橋(渡しをする) library 輸出(する)s two 機能(する)/行事s called
uno_ext_getMapping() and uno_initEnvironment(). The
latter is 現在/一般に 器具/実施するd by the 橋(渡しをする) library for pragmatic 推論する/理由s.
The runtime will lookup an initialization library of an 環境 by 負担ing
a library with 指名する EnvName_uno. uno_getEnvironment()
initializes the 環境, e.g. raises the JVM, 始める,決めるs a 配置する/処分する/したい気持ちにさせるing callback
etc. C++ 環境s usually do nothing.
無効の SAL_CALL uno_initEnvironment(
uno_Environment * pEnv );
The first 機能(する)/行事, uno_ext_getMapping(), is called by the UNO
runtime to get the mappings for both directions. The
uno_ext_getMapping() call receives a source and 目的地
環境 扱う to distinguish which mapping is 需要・要求するd. It is やめる (疑いを)晴らす
that the 橋(渡しをする) library cannot be 荷を降ろすd while any code of it is still
needed, i.e. interfaces are held. So both mappings and any wrapped interface
(proxy) that is 輸出(する)d needs to 修正する a 株d library wide 言及/関連
count.
無効の SAL_CALL uno_ext_getMapping(
uno_Mapping ** ppMapping,
uno_Environment * pFrom, uno_Environment * pTo );
環境
The 意向 of an 環境 (and programmatically 環境 扱うs) is to identify (given by its type 指名する and 状況 pointer) and optionally to 供給する extra functionality like interface 登録.
In 明確な/細部 the latter point is very important, because of the 反対する 身元 of an interface. Any UNO 反対する is defined to 供給する the same instance of XInterface any time it is queried for it. This specification has been made to 実験(する) whether two interfaces belong to the same 反対する (e.g. when 実験(する)ing the source 反対する of an 後継の event). So when interfaces are mapped around to some 環境s outer space, they must 供給する the same XInterface in each 環境 (e.g. in C++, equal XInterface pointers).
Also it is recommended to 再使用する any interface you can, i.e. 減ずるing the construction of proxy interfaces as often as you can, because each 建設するd proxy interface leads の中で the 取得/買収 of 資源s to another indirection when called.
The structure of an 環境 is 分裂(する) into the simple ありふれた "身元" part which can easily be 器具/実施するd by 橋(渡しをする)s that 扱う 反対する 身元 問題/発行するs in their own way. If the 環境 実施 supports interface 登録 functionality etc. then the optional pointer is 始める,決める. Optional functionality is interface 登録, acquiring/ 解放(する)ing interfaces of the 環境 and 得るing 反対する identifiers for an interface.
Interface 登録 is divided into 登録 of proxy and 初めの interfaces. 明白に proxies have to be held unacquired, さもなければ mapped interfaces will never die. The 支配する for a 言及/関連 counted C++ proxy is, that it 登録(する)s itself when 言及/関連 count increments from 0 to 1 and 取り消すs itself when the count decrements from 1 to 0. To synchronize 登録 接近 while not 認めるing 内部の locks on the interface 登録, the proxy will be explicitly 解放する/自由なd by the 環境 by its given freeProxy() 機能(する)/行事 at 登録.
/** The binary specification of an UNO 環境. */
typedef struct _uno_Environment
{
/** reserved for 未来 use (0 if not used)
*/
無効の * pReserved;
/** type 指名する of 環境
*/
rtl_uString * pTypeName;
/** 解放する/自由な 状況 pointer to be used for 明確な/細部 classes of 環境s (e.g., a JVM pointer)
*/
無効の * pContext;
/** pointer to 延長するd 環境 (interface 登録 functionality), if supported
*/
uno_ExtEnvironment * pExtEnv;
/** Acquires this 環境.
@param pEnv this 環境
*/
無効の (SAL_CALL * acquire)( uno_Environment * pEnv );
/** 解放(する)s this 環境;
last 解放(する) of 環境 will 取り消す the 環境 from runtime.
@param pEnv this 環境
*/
無効の (SAL_CALL * 解放(する))( uno_Environment * pEnv );
/** Call this 機能(する)/行事 to explicitly 配置する/処分する/したい気持ちにさせる this 環境
(e.g., 解放(する) all interfaces).
You might want to call this 機能(する)/行事 before shutting 負かす/撃墜する 予定 to a runtime error.
@param pEnv this 環境
*/
無効の (SAL_CALL * 配置する/処分する/したい気持ちにさせる)( uno_Environment * pEnv );
/* ===== the に引き続いて part will be late initialized by a matching 橋(渡しをする) ===== *
* ===== and is NOT for public use. ===== */
/** CALLBACK
配置する/処分する/したい気持ちにさせるing callback 機能(する)/行事 pointer that can be 始める,決める to get signalled before the 環境
is destroyed.
@param pEnv 環境 that is 存在 性質の/したい気がして
*/
無効の (SAL_CALL * environmentDisposing)( uno_Environment * pEnv );
} uno_Environment;
/** Generic 機能(する)/行事 pointer 宣言 to 解放する/自由な a proxy 反対する if it is not needed
by the 環境 anymore.
Any proxy 反対する must 登録(する) itself on first acquire() call and 取り消す
itself on last 解放(する)() call.
This can happen several times because the 環境 (武器などの)隠匿場所s proxy 反対するs
until the 環境 explicitly 解放する/自由なs the proxy 反対する calling this 機能(する)/行事.
@param pEnv 環境
@param pProxy proxy pointer
*/
typedef 無効の (SAL_CALL * uno_freeProxyFunc)( uno_ExtEnvironment * pEnv, 無効の * pProxy );
/** Generic 機能(する)/行事 pointer 宣言 to 配分する memory. Used with getRegisteredInterfaces().
@param nBytes 量 of memory in bytes
@return pointer to 配分するd memory
*/
typedef 無効の * (SAL_CALL * uno_memAlloc)( sal_uInt32 nBytes );
/** The binary specification of an UNO 環境 supporting interface 登録.
*/
typedef struct _uno_ExtEnvironment
{
/** 相続するs all members of an uno_Environment
*/
uno_Environment aBase;
/** 登録(する)s an interface of this 環境.
@param pEnv this 環境
@param ppInterface inout parameter of interface to be 登録(する)d
@param pOId 反対する id of interface
@param pTypeDescr type description of interface
*/
無効の (SAL_CALL * registerInterface)(
uno_ExtEnvironment * pEnv,
無効の ** ppInterface,
rtl_uString * pOId,
typelib_InterfaceTypeDescription * pTypeDescr );
/** 登録(する)s a proxy interface of this 環境 that can be reanimated and is
解放する/自由なd explicitly by this 環境.
@param pEnv this 環境
@param ppInterface inout parameter of interface to be 登録(する)d
@param freeProxy 機能(する)/行事 to 解放する/自由な proxy 反対する
@param pOId 反対する id of interface
@param pTypeDescr type description of interface
*/
無効の (SAL_CALL * registerProxyInterface)(
uno_ExtEnvironment * pEnv,
無効の ** ppProxy,
uno_freeProxyFunc freeProxy,
rtl_uString * pOId,
typelib_InterfaceTypeDescription * pTypeDescr );
/** 取り消すs an interface from this 環境.
You have to 取り消す any interface that has been 登録(する)d 経由で this method.
@param pEnv this 環境
@param pInterface interface to be 取り消すd
*/
無効の (SAL_CALL * revokeInterface)(
uno_ExtEnvironment * pEnv,
無効の * pInterface );
/** 供給するs the 反対する id of a given interface.
@param ppOut inout oid
@param pInterface interface of 反対する
*/
無効の (SAL_CALL * getObjectIdentifier)(
uno_ExtEnvironment * pEnv,
rtl_uString ** ppOId,
無効の * pInterface );
/** Retrieves an interface identified by its 反対する id and type from this 環境.
Interfaces are retrieved in the same order as they are 登録(する)d.
@param pEnv this 環境
@param ppInterface inout parameter for the 登録(する)d interface; (0) if 非,不,無 was 設立する
@param pOId 反対する id of interface to be retrieved
@param pTypeDescr type description of interface to be retrieved
*/
無効の (SAL_CALL * getRegisteredInterface)(
uno_ExtEnvironment * pEnv,
無効の ** ppInterface,
rtl_uString * pOId,
typelib_InterfaceTypeDescription * pTypeDescr );
/** Returns all 現在/一般に 登録(する)d interfaces of this 環境.
The memory 封鎖する 配分するd might be わずかに larger than (*pnLen * sizeof(無効の *)).
@param pEnv this 環境
@param pppInterfaces out param; pointer to array of interface pointers
@param pnLen out param; length of array
@param memAlloc 機能(する)/行事 for 配分するing memory that is passed 支援する
*/
無効の (SAL_CALL * getRegisteredInterfaces)(
uno_ExtEnvironment * pEnv,
無効の *** pppInterfaces,
sal_Int32 * pnLen,
uno_memAlloc memAlloc );
/* ===== the に引き続いて part will be late initialized by a matching 橋(渡しをする) ===== *
* ===== and is NOT for public use. ===== */
/** 計算するs an 反対する id of the given interface; is called by the 環境
実施.
@param pEnv corresponding 環境
@param ppOId out param: 計算するd id
@param pInterface an interface
*/
無効の (SAL_CALL * computeObjectIdentifier)(
uno_ExtEnvironment * pEnv,
rtl_uString ** ppOId, 無効の * pInterface );
/** 機能(する)/行事 to acquire an interface.
@param pEnv corresponding 環境
@param pInterface an interface
*/
無効の (SAL_CALL * acquireInterface)( uno_ExtEnvironment * pEnv, 無効の * pInterface );
/** 機能(する)/行事 to 解放(する) an interface.
@param pEnv corresponding 環境
@param pInterface an interface
*/
無効の (SAL_CALL * releaseInterface)( uno_ExtEnvironment * pEnv, 無効の * pInterface );
} uno_ExtEnvironment;
There is a distinction between 登録(する)d 環境s
and 匿名の/不明の 環境s. You can 得る an 存在するing 環境 by
calling uno_getEnvironment().
If there is no 存在するing one, then uno_getEnvironment()
creates and 登録(する)s a default one 供給するing the 付加 functionality
(interface 登録 etc.). This is the ありふれた way.
In contrast to this you can call uno_createEnvironent()
to create an 匿名の/不明の 環境 giving an 環境's type 指名する
(e.g. "msci") and a 状況 pointer. Creating 匿名の/不明の 環境s
is sensible if you need more than one 環境 of the same type.
You may want to 議定書 any calls from/ to your 構成要素 and one
可能性 is the に引き続いて approach:
- Create an 匿名の/不明の 環境 of type "uno".
- Connect the 登録(する)d uno 環境 and the 匿名の/不明の 環境 経由で the 議定書 橋(渡しをする) "prot_uno_uno".
- Connect the 匿名の/不明の UNO 環境 with the 環境 of your 構成要素 using the C++ 橋(渡しをする) of choice (compiler that 収集するd the 構成要素 code).
- Connect your 開始する,打ち上げるing 環境 (the 環境 from within calls are put) with the 登録(する)d uno 環境.
- 開始する,打ち上げる your 構成要素.
Mapping
A 橋(渡しをする) consists of two mappings. Each mapping is 扶養家族 on its 相当するもの mapping, because 成し遂げるing a call may bring up the need to 変える interfaces from one 環境 to the other (e.g., in parameter interface) and 副/悪徳行為 versa (e.g., return values).
Mapping an interface from 環境 A to 環境 B 伴う/関わるs several steps to keep 跡をつける of 反対する 身元s:
- First the 反対する identifier of an interface is 決定するd by calling getObjectIdentifier() of 環境 A (source 環境).
- Then the 目的地 環境 is asked with the 反対する identifier and type, if there is a already a 登録(する)d interface in use. If this is the 事例/患者 you can use that one and 結局最後にはーなる here.
- If there is no such interface in use, the 橋(渡しをする) will produce a proxy of that type 委任する/代表ing all calls to the given source interface of 環境 A.
- The source interface will be 登録(する)d at 環境 A and the proxy interface will be introduced as a new proxy at 環境 B (registerProxyInterface()).
The whole シナリオ is shown in the big picture.
Microsoft Visual C++ - UNO 橋(渡しをする)
This is a short, source code based description of an UNO 橋(渡しをする) 実施 for C++ 反対するs 収集するd with the Microsoft Visual C++ 4-6. It covers the rudimentary calling stuff which is very 類似の to other compilers but omits exception 扱うing.
Mapping
Mapping an interface from one 環境 to another is transparently done 経由で the 権利 mapping, e.g. like the に引き続いて XFoo interface from UNO to the Microsoft Visual C++ 環境:
Mapping aMapping( "uno", "msci" );
XFoo * pFoo = (XFoo *)aMapping.mapInterface(
pUnoFoo, ::getCppuType( (const 言及/関連< XFoo > *)0 ) );
...
pFoo->妨げる/法廷,弁護士業();
...
pFoo->解放(する)();
The given UNO interface is mapped to the Microsoft world transparently, so you can call methods and catch exceptions as if the calls are 成し遂げるd on an "初めの" Visual C++ 反対する.
To (人命などを)奪う,主張する this goal, the underlying 橋(渡しをする) has to emulate the behaviour and keep the 訂正する 反対する layout of its compiler. This example explains the 橋(渡しをする) from the Microsoft Visual C++ compiler to the binary (C-) UNO specification which is system 扶養家族, but not compiler 扶養家族. You can communicate with UNO 反対するs 収集するd with another compiler just by having an appropriate 橋(渡しをする) to UNO.
C++ Proxy
Under the hood the call 妨げる/法廷,弁護士業() that is 成し遂げるd on the mapped
interface will call on a proxy C++ 反対する that 委任する/代表s the call to its
corresponding UNO interface (the one given to mapInterface()). To
create a C++ proxy, there is already a proxy class you can 修正する for your
needs (header とじ込み/提出する
橋(渡しをする)s/inc/cpp_uno/橋(渡しをする).h).
You usually instantiate this class and 修正する the vtable pointer, giving your
generic vtable. For Microsoft Visual C++ you can use a generic one, because the
反対するs' this pointer is anytime the second stack parameter. On gcc or sunpro5
the first parameter may be the pointer to a struct return space. So for those
compilers you have to 生成するd a vtable for each type that is used.
When the proxy interface is called, the vtable 索引 is 決定するd by the generic vtable and based on this, the method type description. This is the (警察などへの)密告,告訴(状) to get the values from the 加工業者 call stack and 成し遂げる a 派遣(する) call on the 的 UNO interface that the C++ proxy is wrapping.
After the 派遣(する) call has been done, the returned exception (警察などへの)密告,告訴(状) is checked whether a C++ exception has to be 生成するd and raised. If no exception has occurred, the inout/ out parameters have to be reconverted (which is only important for values 代表するing interfaces or values 含む/封じ込めるing interfaces though, because all UNO values are binary 両立できる on a 明確な/細部 計算するing architecture).
The C++ proxy 反対する 持つ/拘留するs the interface origin (i.e. the 的 uno interface) so it can 登録(する) itself at the 環境 on its first acquire() and 取り消す itself on its last 解放(する)() from its 環境.
struct cppu_cppInterfaceProxy : public ::com::sun::星/主役にする::uno::XInterface
{
oslInterlockedCount nRef;
cppu_Bridge * pBridge;
// mapping (警察などへの)密告,告訴(状)
uno_Interface * pUnoI; // wrapped interface
typelib_InterfaceTypeDescription * pTypeDescr;
::rtl::OUString oid;
// 非,不,無 事実上の methods called on 後継の vtable calls #1, #2
inline 無効の SAL_CALL acquireProxy();
inline 無効の SAL_CALL releaseProxy();
// XInterface: these are only here for 模造の, there will be a patched vtable!
事実上の ::com::sun::星/主役にする::uno::Any SAL_CALL queryInterface(
const ::com::sun::星/主役にする::uno::Type & )
{ return ::com::sun::星/主役にする::uno::Any(); } // don't use this, use cppu_queryInterface()!
事実上の 無効の SAL_CALL acquire() {} // don't use this, use cppu_acquire()!
事実上の 無効の SAL_CALL 解放(する)() {} // don't use this, use cppu_release()!
// ctor
inline cppu_cppInterfaceProxy( cppu_Bridge * pBridge_,
uno_Interface * pUnoI_,
typelib_InterfaceTypeDescription * pTypeDescr_,
const ::rtl::OUString & rOId_ );
};
The proxy manages its 言及/関連 count, a pointer to its 橋(渡しをする) to get the 相当するもの mapping, the uno interface it 委任する/代表s calls to, the (interface) type it is emulating and an 反対する identifier (oid).
The type and 反対する identifier are needed to manage 反対するs from several 環境s and 証明する for 反対する 身元 and to 改善する 業績/成果 (no new interface is needed if there is already a 登録(する)d interface in the 環境).
Essentially if a proxy 反対する is created by the Visual C++ compiler, its vtable is patched, which is the very first pointer in the 反対する layout:
無効の SAL_CALL cppu_cppInterfaceProxy_patchVtable(
XInterface * pCppI, typelib_InterfaceTypeDescription * pTypeDescr )
{
static MediateVtables * s_pMediateVtables = 0;
if (! s_pMediateVtables)
{
MutexGuard aGuard( Mutex::getGlobalMutex() );
if (! s_pMediateVtables)
{
static MediateVtables s_aMediateVtables;
s_pMediateVtables = &s_aMediateVtables;
}
}
// nMapFunctionIndexToMemberIndex: 最小限 size of 需要・要求するd vtable
*(const 無効の **)pCppI = s_pMediateVtables->getMediateVtable(
pTypeDescr->nMapFunctionIndexToMemberIndex );
}
The call stack of a 事実上の 機能(する)/行事 call looks like this:
|
相殺する: |
Value: |
|
0 |
return 演説(する)/住所 |
|
4 |
this pointer |
|
[if struct] 8 |
[if struct] pointer to return struct |
|
8 | 12 |
parameter 0 |
|
... |
... |
The proxy vtable (i.e. 機能(する)/行事 pointer array to 成し遂げる polymorphic calls on C++ 反対するs) 決定するs which 機能(する)/行事 should be called (there is an 初期の vtable of 256 機能(する)/行事 slots that is used for any proxy while no proxy 需要・要求するs a larger one):
|
相殺する: |
機能(する)/行事 pointer: |
|
0 |
|
|
4 |
|
|
8 |
|
|
12 |
|
|
... |
... |
The only 仕事 of the proxy vtable for Visual C++ is to 決定する the call 索引 of the uno method that is to be called, so the proxy vtable looks like:
|
相殺する: |
機能(する)/行事 pointer to code: |
|
0 |
mov eax, 0
|
|
4 |
mov eax, 1
|
|
8 |
mov eax, 2
|
|
... |
... |
First the 妨げる/法廷,弁護士業() call reaches the assembler snippet which
決定するs the vtable slot and jumps to a 機能(する)/行事 called
cpp_vtable_call():
/**
* is called on 後継の vtable calls
* (called by asm snippets)
*/
static __declspec(naked) 無効の __cdecl cpp_vtable_call(無効の)
{
__asm
{
sub esp, 8 // space for 即座の return type
押し進める esp
押し進める eax // vtable 索引
mov eax, esp
追加する eax, 16
押し進める eax // 初めの stack ptr
call cpp_mediate
追加する esp, 12
cmp eax, typelib_TypeClass_FLOAT
je Lfloat
cmp eax, typelib_TypeClass_DOUBLE
je Ldouble
cmp eax, typelib_TypeClass_HYPER
je Lhyper
cmp eax, typelib_TypeClass_UNSIGNED_HYPER
je Lhyper
// 残り/休憩(する) is eax
pop eax
追加する esp, 4
ret
Lhyper:
pop eax
pop edx
ret
Lfloat:
fld dword ptr [esp]
追加する esp, 8
ret
Ldouble:
fld qword ptr [esp]
追加する esp, 8
ret
}
}
The cpp_vtable_call() 機能(する)/行事 just calls
cpp_mediate() 供給するing some space for return values returned in
登録(する)s, the vtable slot and 初めの stack pointer. The
cpp_mediate() 機能(する)/行事 returns the type class of the return value
in eax. The type class is used to 決定する where to place return values.
static typelib_TypeClass __cdecl cpp_mediate(
無効の ** pCallStack, sal_Int32 nVtableCall,
sal_Int64 * pRegisterReturn /* space for 登録(する) return */ )
{
OSL_ENSHURE( sizeof(sal_Int32)==sizeof(無効の *), "### 予期しない!" );
// pCallStack: ret adr, this, [ret *], params
// _this_ ptr is patched cppu_XInterfaceProxy 反対する
cppu_cppInterfaceProxy * pThis = static_cast< cppu_cppInterfaceProxy * >(
reinterpret_cast< XInterface * >( pCallStack[1] ) );
typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex,
"### 違法な vtable 索引!" );
if (nVtableCall >= pTypeDescr->nMapFunctionIndexToMemberIndex)
{
throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("違法な vtable 索引!") ),
(XInterface *)pThis );
}
// 決定する called method
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nVtableCall];
OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### 違法な member 索引!" );
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
typelib_TypeClass eRet;
switch (aMemberDescr.get()->eTypeClass)
{
事例/患者 typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nVtableCall)
{
// is GET method
eRet = cpp2uno_call(
pThis, aMemberDescr.get(),
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
0, 0, // no params
pCallStack, pRegisterReturn );
}
else
{
// is SET method
typelib_MethodParameter aParam;
aParam.pTypeRef =
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
aParam.bIn = sal_True;
aParam.bOut = sal_False;
eRet = cpp2uno_call(
pThis, aMemberDescr.get(),
0, // 示すs 無効の return
1, &aParam,
pCallStack, pRegisterReturn );
}
break;
}
事例/患者 typelib_TypeClass_INTERFACE_METHOD:
{
// is METHOD
switch (nVtableCall)
{
// 基準 XInterface vtable calls
事例/患者 1: // acquire()
pThis->acquireProxy(); // 非,不,無 事実上の call!
eRet = typelib_TypeClass_VOID;
break;
事例/患者 2: // 解放(する)()
pThis->releaseProxy(); // 非,不,無 事実上の call!
eRet = typelib_TypeClass_VOID;
break;
事例/患者 0: // queryInterface() 選ぶ
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
OSL_ASSERT( pTD );
XInterface * pInterface = 0;
(*pThis->pBridge->pCppEnv->getRegisteredInterface)(
pThis->pBridge->pCppEnv,
(無効の **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
if (pInterface)
{
uno_any_construct( reinterpret_cast< uno_Any * >( pCallStack[2] ),
&pInterface, pTD, cpp_acquire );
pInterface->解放(する)();
TYPELIB_DANGER_RELEASE( pTD );
*(無効の **)pRegisterReturn = pCallStack[2];
eRet = typelib_TypeClass_ANY;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
} // else 成し遂げる queryInterface()
default:
eRet = cpp2uno_call(
pThis, aMemberDescr.get(),
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
pCallStack, pRegisterReturn );
}
break;
}
default:
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("no member description 設立する!") ),
(XInterface *)pThis );
// is here for 模造の
eRet = typelib_TypeClass_VOID;
}
}
return eRet;
}
The cpp_mediate() 機能(する)/行事 looks up the called vtable 索引, gets the せいにする or method type description, and calls cpp2uno_call(), 成し遂げるing the actual UNO 派遣(する) call.
An 利益/興味ing optimization is done on queryInterface() (vtable
slot 0): Instead of 成し遂げるing the call, the source 環境 is asked for a
登録(する)d interface. If there is no 登録(する)d interface, then the call has to
be 成し遂げるd.
static typelib_TypeClass cpp2uno_call(
cppu_cppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, // 0 示すs 無効の return
sal_Int32 nParams, typelib_MethodParameter * pParams,
無効の ** pCallStack,
sal_Int64 * pRegisterReturn /* space for 登録(する) return */ )
{
// pCallStack: ret, this, [コンビナート/複合体 return ptr], params
char * pCppStack = (char *)(pCallStack +2);
// return
typelib_TypeDescription * pReturnTypeDescr = 0;
if (pReturnTypeRef)
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
無効の * pUnoReturn = 0;
無効の * pCppReturn = 0; // コンビナート/複合体 return ptr: if != 0 && != pUnoReturn, reconversion need
if (pReturnTypeDescr)
{
if (cppu_isSimpleType( pReturnTypeDescr ))
{
pUnoReturn = pRegisterReturn; // direct way for simple types
}
else // コンビナート/複合体 return 経由で ptr (pCppReturn)
{
pCppReturn = *(無効の **)pCppStack;
pCppStack += sizeof(無効の *);
pUnoReturn = (cppu_relatesToInterface( pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize )
: pCppReturn); // direct way
}
}
// stack space
OSL_ENSHURE( sizeof(無効の *) == sizeof(sal_Int32), "### 予期しない size!" );
// parameters
無効の ** pUnoArgs = (無効の **)alloca( 4 * sizeof(無効の *) * nParams );
無効の ** pCppArgs = pUnoArgs + nParams;
// indices of values this have to be 変えるd (interface 転換 cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
sal_Int32 nTempIndizes = 0;
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{
const typelib_MethodParameter & rParam = pParams[nPos];
typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
if (!rParam.bOut && cppu_isSimpleType( pParamTypeDescr )) // value
{
pCppArgs[nPos] = pCppStack;
pUnoArgs[nPos] = pCppStack;
switch (pParamTypeDescr->eTypeClass)
{
事例/患者 typelib_TypeClass_HYPER:
事例/患者 typelib_TypeClass_UNSIGNED_HYPER:
事例/患者 typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to コンビナート/複合体 value | ref
{
pCppArgs[nPos] = *(無効の **)pCppStack;
if (! rParam.bIn) // is pure out
{
// uno out is unconstructed mem!
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
pTempIndizes[nTempIndizes] = nPos;
// will be 解放(する)d at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
// is in/inout
else if (cppu_relatesToInterface( pParamTypeDescr ))
{
uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
*(無効の **)pCppStack, pParamTypeDescr,
&pThis->pBridge->aCpp2Uno );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be 解放(する)d at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
else // direct way
{
pUnoArgs[nPos] = *(無効の **)pCppStack;
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // 基準 parameter length
}
// ExceptionHolder
uno_Any aUnoExc; // Any will be 建設するd by callee
uno_Any * pUnoExc = &aUnoExc;
// invoke uno 派遣(する) call
(*pThis->pUnoI->pDispatcher)( pThis->pUnoI, pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
// in 事例/患者 an exception occurred...
if (pUnoExc)
{
// destruct 一時的な in/inout params
while (nTempIndizes--)
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
if (pParams[nIndex].bIn) // is in/inout => was 建設するd
uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
msci_raiseException( &aUnoExc, &pThis->pBridge->aUno2Cpp ); // has to destruct the any
// is here for 模造の
return typelib_TypeClass_VOID;
}
else // else no exception occurred...
{
// 一時的な params
while (nTempIndizes--)
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
if (pParams[nIndex].bOut) // inout/out
{
// 変える and 割り当てる
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
&pThis->pBridge->aUno2Cpp );
}
// destroy temp uno param
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// return
if (pCppReturn) // has コンビナート/複合体 return
{
if (pUnoReturn != pCppReturn) // needs reconversion
{
uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
&pThis->pBridge->aUno2Cpp );
// destroy temp uno return
uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
}
// コンビナート/複合体 return ptr is 始める,決める to eax
*(無効の **)pRegisterReturn = pCppReturn;
}
if (pReturnTypeDescr)
{
typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
return eRet;
}
else
return typelib_TypeClass_VOID;
}
}
The cpp2uno_call() 機能(する)/行事 reads C++ parameters from the call
stack and 変えるs to binary (C-) UNO, if needed (C++ and UNO values are binary
両立できる 関心ing the memory layout). If the UNO 派遣(する) call has
returned and no exception has been signalled (pUnoExc), all out
parameters are written 支援する to C++.
UNO Stub
If a Visual C++ interface is be mapped to binary UNO (i.e. the 中間の 環境), and that interface is mapped to another compiler 環境, then an UNO stub is created , 委任する/代表ing all UNO 派遣(する) calls to its corresponding C++ interface (in this 事例/患者 Microsoft Visual C++).
後継の calls on the UNO interface (i.e. calls of the 派遣(する) 機能(する)/行事)
are 成し遂げるd by 変えるing the call parameters and 押し進めるing them on the
加工業者 stack, then calling the 需要・要求するd vtable slot on the 目的地
interface.
Any C++ exception is caught and 報告(する)/憶測d as an out parameter to
the 報知係. If no exception occurred, inout/ out parameters are 変えるd and
written.
The UNO stub 実施 is referred as the
cppu_unoInterfaceProxy class, because it 機能(する)/行事s as an UNO proxy
of a C++ interface:
struct cppu_unoInterfaceProxy : public uno_Interface
{
oslInterlockedCount nRef;
cppu_Bridge * pBridge;
// mapping (警察などへの)密告,告訴(状)
::com::sun::星/主役にする::uno::XInterface * pCppI; // wrapped interface
typelib_InterfaceTypeDescription * pTypeDescr;
::rtl::OUString oid;
// ctor
inline cppu_unoInterfaceProxy( cppu_Bridge * pBridge_,
::com::sun::星/主役にする::uno::XInterface * pCppI_,
typelib_InterfaceTypeDescription * pTypeDescr_,
const ::rtl::OUString & rOId_ );
};
The UNO stub manages its 言及/関連 count, a pointer to its 橋(渡しをする) to 接近 its 相当するもの mapping, the C++ interface it 委任する/代表s 後継の 派遣(する) calls to, the (interface) type it is emulating and an 反対する identifier (oid).
The 派遣(する) 機能(する)/行事 uno_Interface::pDispatcher()
distinguishes between せいにする read/ 令状 接近 and method calls from the
UNO 視野, calling the 訂正する C++ 事実上の 機能(する)/行事:
無効の SAL_CALL cppu_unoInterfaceProxy_dispatch(
uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
無効の * pReturn, 無効の * pArgs[], uno_Any ** ppException )
{
// is my surrogate
cppu_unoInterfaceProxy * pThis = static_cast< cppu_unoInterfaceProxy * >( pUnoI );
typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
switch (pMemberDescr->eTypeClass)
{
事例/患者 typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
// 決定する vtable call 索引
sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of 範囲!" );
sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos];
OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### 違法な vtable 索引!" );
typelib_TypeDescriptionReference * pRuntimeExcRef = 0;
if (pReturn)
{
// 扶養家族 派遣(する)
cpp_call( pThis, nVtableCall,
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
0, 0, // no params
1, &pRuntimeExcRef, // RuntimeException
pReturn, pArgs, ppException );
}
else
{
// is SET
typelib_MethodParameter aParam;
aParam.pTypeRef =
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
aParam.bIn = sal_True;
aParam.bOut = sal_False;
typelib_TypeDescriptionReference * pReturnTypeRef = 0;
OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("無効の") );
typelib_typedescriptionreference_new(
&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
// 扶養家族 派遣(する)
cpp_call( pThis, nVtableCall +1, // get, then 始める,決める method
pReturnTypeRef,
1, &aParam,
1, &pRuntimeExcRef,
pReturn, pArgs, ppException );
typelib_typedescriptionreference_release( pReturnTypeRef );
}
break;
}
事例/患者 typelib_TypeClass_INTERFACE_METHOD:
{
// 決定する vtable call 索引
sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of 範囲!" );
sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos];
OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### 違法な vtable 索引!" );
switch (nVtableCall)
{
// 基準 calls
事例/患者 1: // acquire uno interface
(*pUnoI->acquire)( pUnoI );
*ppException = 0;
break;
事例/患者 2: // 解放(する) uno interface
(*pUnoI->解放(する))( pUnoI );
*ppException = 0;
break;
事例/患者 0: // queryInterface() 選ぶ
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
OSL_ASSERT( pTD );
uno_Interface * pInterface = 0;
(*pThis->pBridge->pUnoEnv->getRegisteredInterface)(
pThis->pBridge->pUnoEnv,
(無効の **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
if (pInterface)
{
uno_any_construct( reinterpret_cast< uno_Any * >( pReturn ), &pInterface, pTD, 0 );
(*pInterface->解放(する))( pInterface );
TYPELIB_DANGER_RELEASE( pTD );
*ppException = 0;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
} // else 成し遂げる queryInterface()
default:
// 扶養家族 派遣(する)
cpp_call( pThis, nVtableCall,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nExceptions,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->ppExceptions,
pReturn, pArgs, ppException );
}
break;
}
default:
{
::com::sun::星/主役にする::uno::RuntimeException aExc(
OUString( RTL_CONSTASCII_USTRINGPARAM("違法な member type description!") ),
pThis->pCppI );
typelib_TypeDescription * pTD = 0;
const Type & rExcType = ::getCppuType( (const ::com::sun::星/主役にする::uno::RuntimeException *)0 );
TYPELIB_DANGER_GET( &pTD, rExcType.getTypeLibType() );
uno_any_construct( *ppException, &aExc, pTD, 0 );
TYPELIB_DANGER_RELEASE( pTD );
}
}
}
その上の on cpp_call() is called given the C++ interface
pointer, vtable 索引 and all parameters to 成し遂げる the C++ 事実上の 機能(する)/行事
call. The given parameters are still binary (C-) UNO values that may be
変えるd to fit the compiler 環境 (i.e. an UNO interface must be mapped
to a C++ interface). The cpp_call() 機能(する)/行事 準備するs an array of
longs (stack parameters) and calls callVirtualMethod(), an
議会 機能(する)/行事 成し遂げるing the Microsoft 明確な/細部 事実上の call having the
権利 登録(する)s 始める,決める:
static 無効の cpp_call(
cppu_unoInterfaceProxy * pThis,
sal_Int32 nVtableCall,
typelib_TypeDescriptionReference * pReturnTypeRef,
sal_Int32 nParams, typelib_MethodParameter * pParams,
sal_Int32 nExceptions, typelib_TypeDescriptionReference ** ppExceptionRefs,
無効の * pUnoReturn, 無効の * pUnoArgs[], uno_Any ** ppUnoExc )
{
// max space for: [コンビナート/複合体 ret ptr], values|ptr ...
char * pCppStack = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) );
char * pCppStackStart = pCppStack;
// return
typelib_TypeDescription * pReturnTypeDescr = 0;
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
OSL_ENSHURE( pReturnTypeDescr, "### 推定する/予想するd return type description!" );
無効の * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
if (pReturnTypeDescr)
{
if (cppu_isSimpleType( pReturnTypeDescr ))
{
pCppReturn = pUnoReturn; // direct way for simple types
}
else
{
// コンビナート/複合体 return 経由で ptr
pCppReturn = *(無効の **)pCppStack = (cppu_relatesToInterface( pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize )
: pUnoReturn); // direct way
pCppStack += sizeof(無効の *);
}
}
// stack space
OSL_ENSHURE( sizeof(無効の *) == sizeof(sal_Int32), "### 予期しない size!" );
// args
無効の ** pCppArgs = (無効の **)alloca( 3 * sizeof(無効の *) * nParams );
// indices of values this have to be 変えるd (interface 転換 cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
sal_Int32 nTempIndizes = 0;
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{
const typelib_MethodParameter & rParam = pParams[nPos];
typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
if (!rParam.bOut && cppu_isSimpleType( pParamTypeDescr ))
{
uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
&pThis->pBridge->aUno2Cpp );
switch (pParamTypeDescr->eTypeClass)
{
事例/患者 typelib_TypeClass_HYPER:
事例/患者 typelib_TypeClass_UNSIGNED_HYPER:
事例/患者 typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to コンビナート/複合体 value | ref
{
if (! rParam.bIn) // is pure out
{
// cpp out is 建設するd mem, uno out is not!
uno_constructData(
*(無効の **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pParamTypeDescr );
pTempIndizes[nTempIndizes] = nPos; // default 建設するd for cpp call
// will be 解放(する)d at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
// is in/inout
else if (cppu_relatesToInterface( pParamTypeDescr ))
{
uno_copyAndConvertData(
*(無効の **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pUnoArgs[nPos], pParamTypeDescr,
&pThis->pBridge->aUno2Cpp );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be 解放(する)d at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
else // direct way
{
*(無効の **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // 基準 parameter length
}
// only try-finally/ try-except 声明s possible...
__try
{
__try
{
// pCppI is msci this pointer
callVirtualMethod(
pThis->pCppI, nVtableCall,
pCppReturn, pReturnTypeDescr->eTypeClass,
(sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
// NO exception occurred...
*ppUnoExc = 0;
// reconvert 一時的な params
while (nTempIndizes--)
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
if (pParams[nIndex].bIn)
{
if (pParams[nIndex].bOut) // inout
{
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
&pThis->pBridge->aCpp2Uno );
}
}
else // pure out
{
uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
&pThis->pBridge->aCpp2Uno );
}
// destroy temp cpp param => cpp: every param was 建設するd
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// return value
if (pCppReturn && pUnoReturn != pCppReturn)
{
uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
&pThis->pBridge->aCpp2Uno );
uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
}
}
__except (msci_filterCppException( GetExceptionInformation(),
*ppUnoExc, &pThis->pBridge->aCpp2Uno ))
{
// *ppUnoExc is untouched and any was 建設するd by filter 機能(する)/行事
// __finally 封鎖する will be called
return;
}
}
__finally
{
// cleanup of params was already done in reconversion 宙返り飛行 if no exception occurred;
// this is quicker than getting all param descriptions twice!
// so cleanup only if an exception occurred:
if (*ppUnoExc)
{
// 一時的な params
while (nTempIndizes--)
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
// destroy temp cpp param => cpp: every param was 建設するd
uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
}
// return type
if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
}
}
Finally callVirtualMethod() 成し遂げるs the C++ call, copying the given stack parameters and 蓄える/店ing return values passed 支援する in 登録(する)s.
static 無効の callVirtualMethod(
無効の * pThis, sal_Int32 nVtableIndex,
無効の * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
sal_Int32 * pStackLongs, sal_Int32 nStackLongs )
{
// parameter 名簿(に載せる)/表(にあげる) is mixed 名簿(に載せる)/表(にあげる) of * and values
// 言及/関連 parameters are pointers
OSL_ENSHURE( pStackLongs && pThis, "### null ptr!" );
OSL_ENSHURE( (sizeof(無効の *) == 4) &&
(sizeof(sal_Int32) == 4), "### 予期しない size of int!" );
__asm
{
mov eax, nStackLongs
実験(する) eax, eax
je Lcall
// copy values
mov ecx, eax
shl eax, 2 // sizeof(sal_Int32) == 4
追加する eax, pStackLongs // params stack space
Lcopy: sub eax, 4
押し進める dword ptr [eax]
dec ecx
jne Lcopy
Lcall:
// call
mov ecx, pThis
押し進める ecx // this ptr
mov edx, [ecx] // pvft
mov eax, nVtableIndex
shl eax, 2 // sizeof(無効の *) == 4
追加する edx, eax
call [edx] // interface method call must be __cdecl!!!
// 登録(する) return
mov ecx, eReturnTypeClass
cmp ecx, typelib_TypeClass_VOID
je Lcleanup
mov ebx, pRegisterReturn
// int32
cmp ecx, typelib_TypeClass_LONG
je Lint32
cmp ecx, typelib_TypeClass_UNSIGNED_LONG
je Lint32
cmp ecx, typelib_TypeClass_ENUM
je Lint32
// int8
cmp ecx, typelib_TypeClass_BOOLEAN
je Lint8
cmp ecx, typelib_TypeClass_BYTE
je Lint8
// int16
cmp ecx, typelib_TypeClass_CHAR
je Lint16
cmp ecx, typelib_TypeClass_SHORT
je Lint16
cmp ecx, typelib_TypeClass_UNSIGNED_SHORT
je Lint16
// float
cmp ecx, typelib_TypeClass_FLOAT
je Lfloat
// 二塁打
cmp ecx, typelib_TypeClass_DOUBLE
je Ldouble
// int64
cmp ecx, typelib_TypeClass_HYPER
je Lint64
cmp ecx, typelib_TypeClass_UNSIGNED_HYPER
je Lint64
jmp Lcleanup // no simple type
Lint8:
mov byte ptr [ebx], al
jmp Lcleanup
Lint16:
mov word ptr [ebx], ax
jmp Lcleanup
Lfloat:
fstp dword ptr [ebx]
jmp Lcleanup
Ldouble:
fstp qword ptr [ebx]
jmp Lcleanup
Lint64:
mov dword ptr [ebx], eax
mov dword ptr [ebx+4], edx
jmp Lcleanup
Lint32:
mov dword ptr [ebx], eax
jmp Lcleanup
Lcleanup:
// cleanup stack (obsolete though because of 機能(する)/行事)
mov eax, nStackLongs
shl eax, 2 // sizeof(sal_Int32) == 4
追加する eax, 4 // this ptr
追加する esp, eax
}
}
Author:
Daniel Bölzle ($Date: 2004/12/08 11:16:23 $) |


