473,383 Members | 1,925 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

[?] Querying for C# methods from unmanaged C++ via COM

Hello:

This question relates both to C# and to unmanaged C++, but is not really "C#
specific" at the C# end.

Let us suppose that I have a C# class such that:

using System;
using SomeCOM_Lib;

namespace Foo
{
class Bar : SomeCOM_Lib.ISomeInterface
{
public void SomeMethod() {}
}

class Quux
{
public void SomeCSharpMethod()
{

SomeCOM_Lib.ISomeOtherInterface obj = new
SomeCOM_Lib.ISomeOtherInterface();
obj.TheInterface = obj;
}
}
}

Now, let us suppose in our C++, the put_TheInterface on ISomeOtherInterface
wishes to query TheInterface for the methods of Bar, via the base interface
ISomeInterface (which includes an IDispatch interface).

In other words, from unmanaged C++, given the IDispatch interface of the C#
"obj" -- is there a way to determine the names of the methods on obj, such
that "SomeMethod" can be identified and its ID queried, so it can be invoked
off IDispatch::Invoke?

Essentially, I wish to determine at run-time the methods of a C# class and
call them via IDispatch, without knowing in advance (at compile time) what
those methods are named.

This is to implement a generic "callback" functionality.

Thanks in advance for any pointers.

(At the C++ side, the code should not require the assumption that the .NET
framework is installed. The C# class could, in fact, have been implemented
in unmanaged C++, but in this case just happens to be in C#.)

--
Quinn
Nov 17 '05 #1
3 1978
> class Quux
{
public void SomeCSharpMethod()
{

SomeCOM_Lib.ISomeOtherInterface obj = new
SomeCOM_Lib.ISomeOtherInterface();
obj.TheInterface = obj;
}
}
}


That should have read:

obj.TheInterface = new Bar();
Nov 17 '05 #2
"Quinn Tyler Jackson" <qj******@shaw.ca> wrote in message
news:T1xRb.305864$ts4.291772@pd7tw3no...
This question relates both to C# and to unmanaged C++, but is not really "C# specific" at the C# end.
:-)
In other words, from unmanaged C++, given the IDispatch interface of the C# "obj" -- is there a way to determine the names of the methods on obj, such
that "SomeMethod" can be identified and its ID queried, so it can be invoked off IDispatch::Invoke?

Essentially, I wish to determine at run-time the methods of a C# class and
call them via IDispatch, without knowing in advance (at compile time) what
those methods are named.


Half of what you want to do is easy. Given a managed type (a.k.a class), you
can use reflection to determine the methods that it contains.

http://msdn.microsoft.com/library/de...thodstopic.asp

As to the rest, I pass. :-)

Regards,
Will
Nov 17 '05 #3
"William DePalo [MVP VC++]" said:
Half of what you want to do is easy. Given a managed type (a.k.a class), you can use reflection to determine the methods that it contains.


I cannot believe that I managed to figure out the answer to my own question
by trial and error, but I did.

The key requirements were that:

1. I be able to dynamically register a C# class that my COM object knows
nothing about other than the fact that it has an IDispatch interface. This
requirement precludes using a tool that exports an assembly to the registry
after the fact.

2. I be able to query (from within my COM object) whether or not a C# class
it has been handed as an interface pointer has a given method, by using a
string that is only known at run-time. This precludes using headers at
compile time.

3. That the COM object not in any way "depend" on the .NET framework being
installed. Although in this case I am using C# for testing purposes, the
mechanism was supposed to be generic enough that any COM object that exposes
IDispatch should be able to do what I wanted.

The solution is not exactly "pretty" but it works.

The reason I need this was so that a COM object implemented in unmanaged ATL
that has been imported into a .NET project via Interop could call-back into
the .NET side.

Here is a short snippet of the C#-side of the solution I came up with:
BEGIN


using System;
using METASCOMLib;
using MetaSLua;
using System.Runtime.InteropServices;
using System.Reflection;

namespace CSharpExample
{
[Guid("03911914-DCF0-4caf-A654-5897ED3DC060")]
public interface ITest
{
void b_event();
}

[ClassInterface(ClassInterfaceType.AutoDual)]
public class CSharpEventHost : ITest, IMetaXParserEventHost
{
public CSharpEventHost()
{
}

public Guid ClassGUID
{
get
{
return new Guid("03911914-DCF0-4caf-A654-5897ED3DC060");
}
}

[DispId(15)]
public void b_event()
{
Console.Out.Write("b_event fired\n");
}
}

class ApplicationClass
{
[STAThread]
static void Main(string[] args)
{
RegistrationServices rs = new RegistrationServices();
bool b = rs.RegisterAssembly(Assembly.GetExecutingAssembly( ),
0);

MetaXGrammar gmr = new MetaXGrammar();
gmr.LuaCallbacks = new LuaEvents(Console.Out, Console.Error);
gmr.SetLuaDebug(true, false, false);
gmr.EventHost = new CSharpEventHost();

gmr.Grammar =
"grammar X host Lua {" +
" S ::= a b c;" +
" a ::= '[0-9]+';" +
" b ::= '[a-z]+';" +
" c ::= '[0-9]+';" +

" @function_impls = :{ " +
" function c_event (N)\n" +
" if (N:MATCHED()) then\n" +
" print(N:LEXEME())\n" +
" end\n"+
" end" +
" }:;" +
"};";

if(gmr.IsGood)
{
IMetaXScanInfo r = gmr.Scan("12345 abc 67890 123abc456");

if(r.MatchLength > 0)
{
Console.Write("Lexeme = \"" + r.Lexeme + "\"\n");
Console.Write(gmr.Root.GetChildByPath("S/b").Lexeme + "\n");
}
}
else
{
Console.Write("Error: Grammar could not be compiled!\n");
}

rs.UnregisterAssembly(Assembly.GetExecutingAssembl y());
}
}
}

<< END

As you can see, "b" in the run-time compiled grammar is known only at
run-time, and therefore that "b_event" exists in CSharpEventHost must be
determined at run-time. The grammar could, after all, have been loaded from
a text file.

The tricky part is knowing how to query gmr.EventHost from within the ATL
code that implements METAXCOMLib. I figured it out by trial and error to be
(please pardon the hacky nature of the following C++ -- it was for
proof-of-concept. I'll clean it up later.)

STDMETHODIMP CMetaXGrammar::put_EventHost(IMetaXParserEventHost * newVal)
{
m_pEventHost = newVal;

if(m_pEventHost != NULL)
{
DISPID id = 0;
LCID lid = LOCALE_SYSTEM_DEFAULT;

UINT n = 0;

m_pEventHost->GetTypeInfoCount(&n);

if(n != 0)
{
GUID iid = {{0}};
m_pEventHost->get_ClassGUID(&iid);

IUnknown* p = NULL;
m_pEventHost->QueryInterface(iid, (void**)&p);

if(p != NULL)
{
IDispatch* pID = NULL;
p->QueryInterface(IID_IDispatch, (void**)&pID);

if(pID != NULL)
{
ITypeInfo* pTI = NULL;
HRESULT hr = pID->GetTypeInfo(n, lid, &pTI);

MEMBERID mid = 0;
CComBSTR sN("b_event"); // this could be any string
hr = pTI->GetIDsOfNames(&sN, 1, &mid);

if(hr == S_OK)
{
DISPPARAMS dp = {0};
hr = pID->Invoke(mid, IID_NULL, lid, DISPATCH_METHOD, &dp, NULL, NULL,
NULL);
}

pTI->Release();
pID->Release();
}

p->Release();
}
}
}

return S_OK;
}
--
Quinn
Nov 17 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Bob Rock | last post by:
Hello, in the last few days I've made my first few attempts at creating mixed C++ managed-unmanaged assemblies and looking aftwerwards with ILDASM at what is visible in those assemblies from a...
5
by: Shane | last post by:
I wonder if someone has any ideas about the following. I am currently producing some reports for a manufacturing company who work with metal. A finished part can contain multiple sub-parts to...
1
by: VM | last post by:
I'm working on a win appication that is constantly querying a small-sized DB. Until now, I've been using Selects from within my app but, all of a sudden I remembered of an application I was...
4
by: Grant Stanley | last post by:
Im writting a program in unmanaged C++, and want to access a MS SQL Database. I've done quite a lot of database access stuff in C# before so I'm wanting to use C# for the database access in the...
7
by: Willem van Rumpt | last post by:
Hi all, coming from an unmanaged programming background, I took my time to sort out the IDisposable and finalizer patterns. Just when I thought I had it all conceptually neatly arranged, the...
1
by: Arun | last post by:
Hi, I've got a managed class , inside which I'm instantiating an unmanaged class. If that class has some virtual methods, then while debugging I couldn't jump into the source of that virtual...
8
by: Mas L via DotNetMonster.com | last post by:
Hi, I have a c++ source code which I can compile to be a DLL (in VS.NET 2003). And I need to use it in a C# program. After I compiled/build the C++ code to a DLL, I add it as a Reference in my...
7
by: Carl | last post by:
Hello, I noticed an unexplained (for me) behaviour while wrapping unmanaged virtual methods. This is the test situation: An unmanaged class has four methods defined DoIt1 .. DoIt4. Each...
1
by: Joneleth | last post by:
Hi I know how to call external c functions in c# through DllImport. Now, i'm trying to call a c++ (unmanaged) class method, defined in an external .dll as static int myClass::myMethod, and i...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.