hosting the runtime

  • Thread starter Thread starter Lloyd Dupont
  • Start date Start date
L

Lloyd Dupont

I would like to host the .NET runtime in my (Objective)C application
I wonder what is the API for that.
I have SDK 2.0, I looked in the hosting the runtime section of it, very
succint.
The only 'relevant' function I found was: CorBindToRuntimeEx
but I still don't know how to launch a given (static) method.....

any tip?
 
Lloyd, I think what you are looking for is ICLRRuntimeHost::SetHostControl

Alternatively, if you wish to ask the CLR to give you more control over
resource management, you can use IHostControl::GetHostManager

- Sahil Malik [MVP]
Upcoming ADO.NET 2.0 book - http://tinyurl.com/9bync
 
thanks sahil!

mmhh...

on the other hand I never used COM interface, I have no idea on how they
work....
care writing me a veyr simple C:main() which load an exe?

which compile whi gcc ?!?! :D

I just read your article on 21st centure labor in America! hehe.. many
indian in Australia as well ;) ..
 
Lloyd, one of the guys on codebetter is Geoff Appleby who is an Aussie, and
being an Indian, I have friends everywhere (yup there are a lot of indians,
must be some fertility drug). I was having this discussion with Geoff
regards the lifestyle there etc. and in general with my friends - trust me
Aus ain't so bad.

Regards your actual issue hehe :) .. Well, I have used COM heavily under
Windows. So I can tell you how to use it under windows, but the usage
shouldn't be too different under Mac. You might run into platform specific
weirdness though because COM is at a lower level than .NET. I'd first
recommend looking at third party solutions if any have been developed that
allow you to leverage a COM component on a Mac (damn I really want to
program on a Mac someday in my life :-)).

So a COM component has a lot to be told about - more than I can possibly
type here. I'd recommend Inside COM by Don Box.

Straight forward way to instantiate a COM component = CoCreateInstance ==>
Not sure if u have this on a Mac.
Non straightforward way - do what CoCreateInstance does -

Any Com component must export the followign 4 functions -
DllRegisterServer, DllUnregisterServer, DllGetClassObject and
DllCanUnloadNow. Check and see if MSCOREE supports IDispatch - if it does,
your life just got a lot simpler. If it doesn't, no biggie, you can use
DllGetClassObject to get the appropriate class factory. Once you have that,
you can easily create an instance of the interface and call the relevant
functions.

At the very heart of any COM Component are 3 methods that define the
IUnknown interface -

QueryInterface - Do you support interface xxx? If so give me an instance and
increase your reference count.
AddRef - Increase your reference count
Release - Decrease your reference count, if it becomes zero - unload
yourself.

Remember, unlike .NET you are now responsible for destroying what you create
(memory management), thus the AddRef and Release methods. The first
instantiation automatically calls AddRef for you once. I suggest picking up
a good book because it is simply impossible for me to give you a 5 minute
COM tutorial. But do let me know if you have any specific questions.

Also, it is quite possible that someone on a Mac has created third party
libraries that make your life simpler - like on a WinX platform you have VB6
... hehe :). I am unaware of any of those libraries, but I'd certainly google
for 'em if I were u .

- Sahil Malik [MVP]
Upcoming ADO.NET 2.0 book - http://tinyurl.com/9bync
 
Who's talking about the Mac here? Am I missing something.
The CLR hosting COM based interface as implemented in mscoree is not
available on other platforms than Windows, so I'm totaly lost on what your
are talking about.

Willy.
 
Sahil said:
So a COM component has a lot to be told about - more than I can
possibly type here. I'd recommend Inside COM by Don Box.

Hmmm, Inside COM was written by Dale Rogerson, and IMO not particularly
relevant here. Don's book is Essential COM. ;-)

First, its worth pointing out that a COM interface is very much like a
C++ v-table. Imagine COM marshalling as being a mechanism to transport a
v-table from one COM object in one memory space and make it available in
another memory space.

COM itself is essentially a mechanism to manage DLLs (we'll ignore
'local servers'). Imagine that you want to create an instance of a class
class and you know the name of the DLL. The problem in Win32 is that you
first have to locate the DLL and load it - this is the DLL hell problem,
because LoadLibrary will look in various places for the DLL and may pick
up a different version of the DLL or even a totally different DLL that
has the same name. COM manages this through values in the registry, when
you install a COM server the classes it contains will be registered in
the registry and these entries will contain the full path to the DLL.
***It is vitally important that the location of a COM server DLL does
not change***. Each class has a unique name called a GUID (a 128 bit
integer) and so whenever you create an object you create it via its
GUID. Languages do have mappings to human readable names, but it is
important to realise that the real name of a class is the GUID. COM
provides APIs that when given a GUID will locate and load the DLL
containing the class.

Next you need to create an instance of the class, which means finding
some code that will create it for you. Since you don't want a memory
leak, you also have to have a mechanism to remove the instance. COM
objects are usually created by class factory objects, a class factory is
intimately intwined with an object because the class factory calls new
with whatever memory manager it wants to use, and hence when the object
is destroyed it must call the appropriate delete.

So you need to get access to a class factory object in the DLL. However,
DLLs can only export C functions. So all COM server DLLs have to export
a function called DllGetClassObject. In effect you pass the name (GUID)
of a class to this function and it will return the class factory
interface of the class factory object (remember an interface is just a
v-table pointer, so all you get back is a pointer to a table of
pointers). You can then call the IClassFactory::CreateInstance to create
an instance of the class. Note that *all* access to COM objects are via
interfaces so you need to provide an identifier about what interface you
want to have on the new object.

All COM objects must implement IUnknown which has three methods:
QueryInterface allows you to ask for a specific interface, it's
equivalent to the C++ dynamic_cast<>. Note that there is no mechanism to
get a list of the interfaces on an object, instead, you have to call
QueryInterface for the interfaces that you want to use. The other two
methods are AddRef and Release. These maintain a reference count
(usually on the object) and when you make a copy of an interface pointer
you have to call AddRef, when you no longer need the pointer you have to
call Release. Once the reference count falls to zero the object can
delete itself. (What this means is up to the object, but it usually
means calling the delete on its this pointer that corresponds to the new
that the class factory called.)

The beauty of interfaces is that it allows polymorphism, because a
method that takes an interface pointer does not care what object the
pointer points to, it just cares about the behaviour of the interface.
Non straightforward way - do what CoCreateInstance does -

You pass the class's GUID and the indentifier (another GUID) of the
interface you want on the object to CCI, which will locate the DLL, call
the class factory, create the object and then query for the specified
interface.

When you create a COM interface you write the interface in IDL and
compile it with MIDL. MIDL will create a header file with a C++ and a C
mapping for the interface. The platform SDK contains MIDL generated
header files created for the standard interfaces. For example, here's
IUnknown C mapping from unknwn.h:

typedef struct IUnknownVtbl
{
BEGIN_INTERFACE

HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);

ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);

ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);

END_INTERFACE
} IUnknownVtbl;

interface IUnknown
{
CONST_VTBL struct IUnknownVtbl *lpVtbl;
};

So when you call CoCreateInstance in C you will get back an IUnknown* to
call a method you need to derefernce it to get the lpVtbl, and then
dereference that to get to the function pointer that you want to call.
In C++ the interface is treated as a C++ class v-table (the language
mapping does this) so you only need to dereference it once. Also, the
first, implicit parameter of a v-table method is a this pointer. The C++
mapping masks this, but in C you have to pass it explicitly.

// C code
IUnknown* pUnk = NULL;
HRESULT hr;

CoInitialize(); // must initialize COM, this creates a single threaded
apartment
hr = CoCreateInstance(&CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
&IID_IUnknown, &pUnk);
if (SUCCEEDED(hr)) // always check return values
{
// use the interface here...

// finished with the interface so call Release
pUnk->lpVtbl->Release(pUnk);
// in C++ this would be pUnk->Release();
}
CoUninitialize(); // must uninitialise COM

As you can see it is much easier in C++ so usually people don't bother
with C. The only book that I know off hand that shows how to program COM
in C is Brockschmidt's Inside OLE. However, I doubt if this is still in
print. Anyway if you are a proficient C programmer it should not be too
difficult to write C to access COM objects using the headers created by
MIDL.

Richard
 
Holy cow Richard, I admire the effort you put in this answer. And yes, Dale
Rogerson was the author I was referring to. Thats an awesome book IMO. BTW,
I've read your book on ATL+COM. Another good book.

- Sahil Malik [MVP]
Upcoming ADO.NET 2.0 book - http://tinyurl.com/9bync
----------------------------------------------------------------------------


Richard Grimes said:
Sahil said:
So a COM component has a lot to be told about - more than I can
possibly type here. I'd recommend Inside COM by Don Box.

Hmmm, Inside COM was written by Dale Rogerson, and IMO not particularly
relevant here. Don's book is Essential COM. ;-)

First, its worth pointing out that a COM interface is very much like a C++
v-table. Imagine COM marshalling as being a mechanism to transport a
v-table from one COM object in one memory space and make it available in
another memory space.

COM itself is essentially a mechanism to manage DLLs (we'll ignore 'local
servers'). Imagine that you want to create an instance of a class class
and you know the name of the DLL. The problem in Win32 is that you first
have to locate the DLL and load it - this is the DLL hell problem, because
LoadLibrary will look in various places for the DLL and may pick up a
different version of the DLL or even a totally different DLL that has the
same name. COM manages this through values in the registry, when you
install a COM server the classes it contains will be registered in the
registry and these entries will contain the full path to the DLL. ***It is
vitally important that the location of a COM server DLL does not
change***. Each class has a unique name called a GUID (a 128 bit integer)
and so whenever you create an object you create it via its GUID. Languages
do have mappings to human readable names, but it is important to realise
that the real name of a class is the GUID. COM provides APIs that when
given a GUID will locate and load the DLL containing the class.

Next you need to create an instance of the class, which means finding some
code that will create it for you. Since you don't want a memory leak, you
also have to have a mechanism to remove the instance. COM objects are
usually created by class factory objects, a class factory is intimately
intwined with an object because the class factory calls new with whatever
memory manager it wants to use, and hence when the object is destroyed it
must call the appropriate delete.

So you need to get access to a class factory object in the DLL. However,
DLLs can only export C functions. So all COM server DLLs have to export a
function called DllGetClassObject. In effect you pass the name (GUID) of a
class to this function and it will return the class factory interface of
the class factory object (remember an interface is just a v-table pointer,
so all you get back is a pointer to a table of pointers). You can then
call the IClassFactory::CreateInstance to create an instance of the class.
Note that *all* access to COM objects are via interfaces so you need to
provide an identifier about what interface you want to have on the new
object.

All COM objects must implement IUnknown which has three methods:
QueryInterface allows you to ask for a specific interface, it's equivalent
to the C++ dynamic_cast<>. Note that there is no mechanism to get a list
of the interfaces on an object, instead, you have to call QueryInterface
for the interfaces that you want to use. The other two methods are AddRef
and Release. These maintain a reference count (usually on the object) and
when you make a copy of an interface pointer you have to call AddRef, when
you no longer need the pointer you have to call Release. Once the
reference count falls to zero the object can delete itself. (What this
means is up to the object, but it usually means calling the delete on its
this pointer that corresponds to the new that the class factory called.)

The beauty of interfaces is that it allows polymorphism, because a method
that takes an interface pointer does not care what object the pointer
points to, it just cares about the behaviour of the interface.
Non straightforward way - do what CoCreateInstance does -

You pass the class's GUID and the indentifier (another GUID) of the
interface you want on the object to CCI, which will locate the DLL, call
the class factory, create the object and then query for the specified
interface.

When you create a COM interface you write the interface in IDL and compile
it with MIDL. MIDL will create a header file with a C++ and a C mapping
for the interface. The platform SDK contains MIDL generated header files
created for the standard interfaces. For example, here's IUnknown C
mapping from unknwn.h:

typedef struct IUnknownVtbl
{
BEGIN_INTERFACE

HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);

ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);

ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);

END_INTERFACE
} IUnknownVtbl;

interface IUnknown
{
CONST_VTBL struct IUnknownVtbl *lpVtbl;
};

So when you call CoCreateInstance in C you will get back an IUnknown* to
call a method you need to derefernce it to get the lpVtbl, and then
dereference that to get to the function pointer that you want to call. In
C++ the interface is treated as a C++ class v-table (the language mapping
does this) so you only need to dereference it once. Also, the first,
implicit parameter of a v-table method is a this pointer. The C++ mapping
masks this, but in C you have to pass it explicitly.

// C code
IUnknown* pUnk = NULL;
HRESULT hr;

CoInitialize(); // must initialize COM, this creates a single threaded
apartment
hr = CoCreateInstance(&CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
&IID_IUnknown, &pUnk);
if (SUCCEEDED(hr)) // always check return values
{
// use the interface here...

// finished with the interface so call Release
pUnk->lpVtbl->Release(pUnk);
// in C++ this would be pUnk->Release();
}
CoUninitialize(); // must uninitialise COM

As you can see it is much easier in C++ so usually people don't bother
with C. The only book that I know off hand that shows how to program COM
in C is Brockschmidt's Inside OLE. However, I doubt if this is still in
print. Anyway if you are a proficient C programmer it should not be too
difficult to write C to access COM objects using the headers created by
MIDL.

Richard
 
hehe...
well I'm porting a Mac product to Windows.
I use GNUstep to compile the same class data on the 2 platform.
However on Windows will use a .NET GUI. And my question was for a Windows C
loader (compiled with GCC as it will be ObjectiveC code..., but in fact need
not to be, after reflection...)

I had some weird memory corruption in a very simple test program while
loading libraries.
It's why I'm attempting a C loader, so I could load GNUstep first.
Anyway now I uninstall beta 1 that might be the source of the problem, will
see..
 
Anyway, I finally write a tiny, almost correct loader (well can't be sure,
it doesn't link :( yet..), I attached it for academic purpose (hehe, doesn't
that souds good when said like that?)

I'll try to compile with VS next, I might have more success than with gcc?
(I can't be sure yet, now I'm uninstalling problem, I think I get messed up
by beta 1/ beta 2)

Anyway, using COM doesn't seems so hard, there is just the magic about find
the right GUID_xxxx and knowing you have this std Release method...

And yup, Aussie is definitely a good place. I'm french originally (although
Australia born ;)..
And for waht I read on the news I hesitate between America is great or
America is not such a good place to have a good life in....


Sahil Malik said:
Holy cow Richard, I admire the effort you put in this answer. And yes,
Dale
Rogerson was the author I was referring to. Thats an awesome book IMO.
BTW,
I've read your book on ATL+COM. Another good book.

- Sahil Malik [MVP]
Upcoming ADO.NET 2.0 book - http://tinyurl.com/9bync
----------------------------------------------------------------------------


Richard Grimes said:
Sahil said:
So a COM component has a lot to be told about - more than I can
possibly type here. I'd recommend Inside COM by Don Box.

Hmmm, Inside COM was written by Dale Rogerson, and IMO not particularly
relevant here. Don's book is Essential COM. ;-)

First, its worth pointing out that a COM interface is very much like a
C++
v-table. Imagine COM marshalling as being a mechanism to transport a
v-table from one COM object in one memory space and make it available in
another memory space.

COM itself is essentially a mechanism to manage DLLs (we'll ignore 'local
servers'). Imagine that you want to create an instance of a class class
and you know the name of the DLL. The problem in Win32 is that you first
have to locate the DLL and load it - this is the DLL hell problem,
because
LoadLibrary will look in various places for the DLL and may pick up a
different version of the DLL or even a totally different DLL that has the
same name. COM manages this through values in the registry, when you
install a COM server the classes it contains will be registered in the
registry and these entries will contain the full path to the DLL. ***It
is
vitally important that the location of a COM server DLL does not
change***. Each class has a unique name called a GUID (a 128 bit integer)
and so whenever you create an object you create it via its GUID.
Languages
do have mappings to human readable names, but it is important to realise
that the real name of a class is the GUID. COM provides APIs that when
given a GUID will locate and load the DLL containing the class.

Next you need to create an instance of the class, which means finding
some
code that will create it for you. Since you don't want a memory leak, you
also have to have a mechanism to remove the instance. COM objects are
usually created by class factory objects, a class factory is intimately
intwined with an object because the class factory calls new with whatever
memory manager it wants to use, and hence when the object is destroyed it
must call the appropriate delete.

So you need to get access to a class factory object in the DLL. However,
DLLs can only export C functions. So all COM server DLLs have to export a
function called DllGetClassObject. In effect you pass the name (GUID) of
a
class to this function and it will return the class factory interface of
the class factory object (remember an interface is just a v-table
pointer,
so all you get back is a pointer to a table of pointers). You can then
call the IClassFactory::CreateInstance to create an instance of the
class.
Note that *all* access to COM objects are via interfaces so you need to
provide an identifier about what interface you want to have on the new
object.

All COM objects must implement IUnknown which has three methods:
QueryInterface allows you to ask for a specific interface, it's
equivalent
to the C++ dynamic_cast<>. Note that there is no mechanism to get a list
of the interfaces on an object, instead, you have to call QueryInterface
for the interfaces that you want to use. The other two methods are AddRef
and Release. These maintain a reference count (usually on the object) and
when you make a copy of an interface pointer you have to call AddRef,
when
you no longer need the pointer you have to call Release. Once the
reference count falls to zero the object can delete itself. (What this
means is up to the object, but it usually means calling the delete on its
this pointer that corresponds to the new that the class factory called.)

The beauty of interfaces is that it allows polymorphism, because a method
that takes an interface pointer does not care what object the pointer
points to, it just cares about the behaviour of the interface.
Non straightforward way - do what CoCreateInstance does -

You pass the class's GUID and the indentifier (another GUID) of the
interface you want on the object to CCI, which will locate the DLL, call
the class factory, create the object and then query for the specified
interface.
on the other hand I never used COM interface, I have no idea on how
they work....
care writing me a veyr simple C:main() which load an exe?

When you create a COM interface you write the interface in IDL and
compile
it with MIDL. MIDL will create a header file with a C++ and a C mapping
for the interface. The platform SDK contains MIDL generated header files
created for the standard interfaces. For example, here's IUnknown C
mapping from unknwn.h:

typedef struct IUnknownVtbl
{
BEGIN_INTERFACE

HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);

ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);

ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);

END_INTERFACE
} IUnknownVtbl;

interface IUnknown
{
CONST_VTBL struct IUnknownVtbl *lpVtbl;
};

So when you call CoCreateInstance in C you will get back an IUnknown* to
call a method you need to derefernce it to get the lpVtbl, and then
dereference that to get to the function pointer that you want to call. In
C++ the interface is treated as a C++ class v-table (the language mapping
does this) so you only need to dereference it once. Also, the first,
implicit parameter of a v-table method is a this pointer. The C++ mapping
masks this, but in C you have to pass it explicitly.

// C code
IUnknown* pUnk = NULL;
HRESULT hr;

CoInitialize(); // must initialize COM, this creates a single threaded
apartment
hr = CoCreateInstance(&CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
&IID_IUnknown, &pUnk);
if (SUCCEEDED(hr)) // always check return values
{
// use the interface here...

// finished with the interface so call Release
pUnk->lpVtbl->Release(pUnk);
// in C++ this would be pUnk->Release();
}
CoUninitialize(); // must uninitialise COM

As you can see it is much easier in C++ so usually people don't bother
with C. The only book that I know off hand that shows how to program COM
in C is Brockschmidt's Inside OLE. However, I doubt if this is still in
print. Anyway if you are a proficient C programmer it should not be too
difficult to write C to access COM objects using the headers created by
MIDL.

Richard
 
Back
Top