Callback Method Delegate as an Argument to Dll Functions

J

John Bowman

Hello,

I need some help getting a callback delegate passed as an argument to a
dynamically linked Dll method so it in turn, can eventually call it. Below
is the salient portions of code I'm dealing with. It all compiles and all
other dynamically linked methods that only pass "regular" arguments
(strings, ints, bools, objects, etc.) work great. However, when this
portion of code runs and hits the line that acutally invokes the Dll method,
it throws the following exception:

"Object type cannot be converted to target type."

Why am I not allowed to pass the callback delegate: cbMyCallBack to the Dll
method?
Why is it trying to convert the argument at all when the Dll callee method
and the argument type match?


Any help would be appreciated, TIA.


GloballyDelcared:

public delegate void NotifyCB();



Inside Object1:

public void SomeWorkerMethod()

{

....

Object2.DoWork(new NotifyCB(cbTheCallBack))

....

}

public static void cbTheCallBack()

{

//Do the callback here ...

}





Inside Object2:

private Assembly m_DllAssembly = Assembly.Load(DllName);

private Type m_oTypeEngine = =
m_DllAssembly.GetType("Namespace.ObjectName");

private object m_oActivator = Activator.CreateInstance(m_oTypeEngine);

private Type m_TypeInterface = =
m_oTypeEngine.GetInterface("InterfaceName");

private MethodInfo m_miMyDllMethod =
m_TypeInterface.GetMethod("MyDllMethod");;

....

public void DoWork(NotifyCB cbMyCallBack)

{

....

object[] oArgs = {cbMyCallBack};

bool bRtn = (bool)m_miMyDllMethod.Invoke(m_oActivator, oArgs);

....

}





Inside the Called DLL, Object3:

public void MyDllMethod(NotifyCB cbMyCallBack)

{

....

//Do some DLL work

....

cbMyCallBack();

}
 
J

John Bowman

Please note: during the copying and pasting / sanitization process of the
code I included, I've introduced several typos that are not really part of
the code, such as = = where it should not be, multiple ;'s, etc. Please
ignore them.

TIA,

John
 
J

John Bowman

Another Please note:

The Exception thrown is an ArgumentException with the message:

"Object type cannot be converted to target type."


TIA... again,

John
 
G

Grant Richins [MS]

What exactly do you mean by "GloballyDeclared"? I'm guessing that you've
got 2 projects each with their own copy of "public delegate void
NotifyCB();" which the runtime then treats as 2 distinct delegates types
that have no conversion. I believe the proper fix would be for one or the
other project to define NotifyCB, and then the other project needs to
reference it. Looking at your overall layout, I would guess the definition
of NotifyCB should exist in Object2's project.

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.


John Bowman [email protected]> said:
Another Please note:

The Exception thrown is an ArgumentException with the message:

"Object type cannot be converted to target type."


TIA... again,

John


John Bowman [email protected]> said:
Hello,

I need some help getting a callback delegate passed as an argument to a
dynamically linked Dll method so it in turn, can eventually call it. Below
is the salient portions of code I'm dealing with. It all compiles and all
other dynamically linked methods that only pass "regular" arguments
(strings, ints, bools, objects, etc.) work great. However, when this
portion of code runs and hits the line that acutally invokes the Dll method,
it throws the following exception:

"Object type cannot be converted to target type."

Why am I not allowed to pass the callback delegate: cbMyCallBack to the Dll
method?
Why is it trying to convert the argument at all when the Dll callee method
and the argument type match?


Any help would be appreciated, TIA.


GloballyDelcared:

public delegate void NotifyCB();



Inside Object1:

public void SomeWorkerMethod()

{

...

Object2.DoWork(new NotifyCB(cbTheCallBack))

...

}

public static void cbTheCallBack()

{

//Do the callback here ...

}





Inside Object2:

private Assembly m_DllAssembly = Assembly.Load(DllName);

private Type m_oTypeEngine = =
m_DllAssembly.GetType("Namespace.ObjectName");

private object m_oActivator = Activator.CreateInstance(m_oTypeEngine);

private Type m_TypeInterface = =
m_oTypeEngine.GetInterface("InterfaceName");

private MethodInfo m_miMyDllMethod =
m_TypeInterface.GetMethod("MyDllMethod");;

...

public void DoWork(NotifyCB cbMyCallBack)

{

...

object[] oArgs = {cbMyCallBack};

bool bRtn = (bool)m_miMyDllMethod.Invoke(m_oActivator, oArgs);

...

}





Inside the Called DLL, Object3:

public void MyDllMethod(NotifyCB cbMyCallBack)

{

...

//Do some DLL work

...

cbMyCallBack();

}



--
John C. Bowman
Software Engineer
Thermo Electron Scientific Instruments Div.
<Remove this before reply> (e-mail address removed)
 
J

John Bowman

Grant,

Thanks for the info. & response.What I meant by Globally Declared was that I
have a .CS file that defines it and that file is shared in both projects as
you surmised. But I did not realize the runtime would treat them as 2
distinct delegate types.

I'll take another look at it in the morning and try your idea and let you
know if it works.

Thanks!

John

Grant Richins said:
What exactly do you mean by "GloballyDeclared"? I'm guessing that you've
got 2 projects each with their own copy of "public delegate void
NotifyCB();" which the runtime then treats as 2 distinct delegates types
that have no conversion. I believe the proper fix would be for one or the
other project to define NotifyCB, and then the other project needs to
reference it. Looking at your overall layout, I would guess the definition
of NotifyCB should exist in Object2's project.

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.


John Bowman [email protected]> said:
Another Please note:

The Exception thrown is an ArgumentException with the message:

"Object type cannot be converted to target type."


TIA... again,

John


"John Bowman (e-mail address removed)>" <<Remove this before reply> wrote in
message news:[email protected]...
Hello,

I need some help getting a callback delegate passed as an argument to a
dynamically linked Dll method so it in turn, can eventually call it. Below
is the salient portions of code I'm dealing with. It all compiles and all
other dynamically linked methods that only pass "regular" arguments
(strings, ints, bools, objects, etc.) work great. However, when this
portion of code runs and hits the line that acutally invokes the Dll method,
it throws the following exception:

"Object type cannot be converted to target type."

Why am I not allowed to pass the callback delegate: cbMyCallBack to
the
Dll
method?
Why is it trying to convert the argument at all when the Dll callee method
and the argument type match?


Any help would be appreciated, TIA.


GloballyDelcared:

public delegate void NotifyCB();



Inside Object1:

public void SomeWorkerMethod()

{

...

Object2.DoWork(new NotifyCB(cbTheCallBack))

...

}

public static void cbTheCallBack()

{

//Do the callback here ...

}





Inside Object2:

private Assembly m_DllAssembly = Assembly.Load(DllName);

private Type m_oTypeEngine = =
m_DllAssembly.GetType("Namespace.ObjectName");

private object m_oActivator = Activator.CreateInstance(m_oTypeEngine);

private Type m_TypeInterface = =
m_oTypeEngine.GetInterface("InterfaceName");

private MethodInfo m_miMyDllMethod =
m_TypeInterface.GetMethod("MyDllMethod");;

...

public void DoWork(NotifyCB cbMyCallBack)

{

...

object[] oArgs = {cbMyCallBack};

bool bRtn = (bool)m_miMyDllMethod.Invoke(m_oActivator, oArgs);

...

}





Inside the Called DLL, Object3:

public void MyDllMethod(NotifyCB cbMyCallBack)

{

...

//Do some DLL work

...

cbMyCallBack();

}



--
John C. Bowman
Software Engineer
Thermo Electron Scientific Instruments Div.
<Remove this before reply> (e-mail address removed)
 
J

John Bowman

Grant,

I tried your suggestion, but alas it still responds the same way. What
exactly did you mean by "and then the other project needs to reference it"?
If you mean I need to set a reference in the Dll to the cleint's project, I
can't do that because that's the EXE and you can't set references to EXE's.
If you mean I need to set a reference in the EXE project to the Dll, I can't
do that either because the Dll is unknown (except that it supports a
particular interface) until runtime and is totally on it's own and MUST use
late binding..

It would seem to me that passing a function pointer into a late bound Dll
method should be straightforward and common occurance. Is there some reason
one should be prevented from doing this? If so, I suppose I could try
triggering a special custom event. Unfortunately, my fear is that it won't
work either because the unknown Dll would have to support triggering the
special custom event. How can you enforce that when only methods are allowed
to be part of the interface?

Any more ideas/suggestions?

TIA,

John



John Bowman [email protected]> said:
Grant,

Thanks for the info. & response.What I meant by Globally Declared was that I
have a .CS file that defines it and that file is shared in both projects as
you surmised. But I did not realize the runtime would treat them as 2
distinct delegate types.

I'll take another look at it in the morning and try your idea and let you
know if it works.

Thanks!

John

Grant Richins said:
What exactly do you mean by "GloballyDeclared"? I'm guessing that you've
got 2 projects each with their own copy of "public delegate void
NotifyCB();" which the runtime then treats as 2 distinct delegates types
that have no conversion. I believe the proper fix would be for one or the
other project to define NotifyCB, and then the other project needs to
reference it. Looking at your overall layout, I would guess the definition
of NotifyCB should exist in Object2's project.

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.


"John Bowman (e-mail address removed)>" <<Remove this before reply> wrote in
message news:[email protected]...
wrote
to
a
dynamically linked Dll method so it in turn, can eventually call it. Below
is the salient portions of code I'm dealing with. It all compiles
and
all
other dynamically linked methods that only pass "regular" arguments
(strings, ints, bools, objects, etc.) work great. However, when this
portion of code runs and hits the line that acutally invokes the Dll
method,
it throws the following exception:

"Object type cannot be converted to target type."

Why am I not allowed to pass the callback delegate: cbMyCallBack to the
Dll
method?
Why is it trying to convert the argument at all when the Dll callee method
and the argument type match?


Any help would be appreciated, TIA.


GloballyDelcared:

public delegate void NotifyCB();



Inside Object1:

public void SomeWorkerMethod()

{

...

Object2.DoWork(new NotifyCB(cbTheCallBack))

...

}

public static void cbTheCallBack()

{

//Do the callback here ...

}





Inside Object2:

private Assembly m_DllAssembly = Assembly.Load(DllName);

private Type m_oTypeEngine = =
m_DllAssembly.GetType("Namespace.ObjectName");

private object m_oActivator = Activator.CreateInstance(m_oTypeEngine);

private Type m_TypeInterface = =
m_oTypeEngine.GetInterface("InterfaceName");

private MethodInfo m_miMyDllMethod =
m_TypeInterface.GetMethod("MyDllMethod");;

...

public void DoWork(NotifyCB cbMyCallBack)

{

...

object[] oArgs = {cbMyCallBack};

bool bRtn = (bool)m_miMyDllMethod.Invoke(m_oActivator, oArgs);

...

}





Inside the Called DLL, Object3:

public void MyDllMethod(NotifyCB cbMyCallBack)

{

...

//Do some DLL work

...

cbMyCallBack();

}



--
John C. Bowman
Software Engineer
Thermo Electron Scientific Instruments Div.
<Remove this before reply> (e-mail address removed)
 
J

Jon Skeet [C# MVP]

I tried your suggestion, but alas it still responds the same way. What
exactly did you mean by "and then the other project needs to reference it"?
If you mean I need to set a reference in the Dll to the cleint's project, I
can't do that because that's the EXE and you can't set references to EXE's.

See http://www.pobox.com/~skeet/csharp/plugin.html

It's not dealing with delegates specifically, but it should give you an
idea of the options.
 
J

John Bowman

Jon,

Thanks for the link and insight, if gives me an idea to at leat try. What I
still don't understand is since I'm passing the delegate as an argument why
doesn't the Dll code recieve what's passed in and ues it at runtime, rather
than creating a separate delegate inside dll? I must be missing something...
:) .

John
 
J

John Bowman

Jon,

I tried it out and it works great. Thanks for the link/help!

John

John Bowman [email protected]> said:
Jon,

Thanks for the link and insight, if gives me an idea to at leat try. What I
still don't understand is since I'm passing the delegate as an argument why
doesn't the Dll code recieve what's passed in and ues it at runtime, rather
than creating a separate delegate inside dll? I must be missing something...
:) .

John
 
J

Jon Skeet [C# MVP]

Thanks for the link and insight, if gives me an idea to at leat try. What I
still don't understand is since I'm passing the delegate as an argument why
doesn't the Dll code recieve what's passed in and ues it at runtime, rather
than creating a separate delegate inside dll? I must be missing something...
:) .

I don't believe it's creating a separate delegate - I believe it's not
able to reconcile what is passed to it as the type of delegate it is
expecting. Then again, I haven't looked at the code in detail.
 
J

John Bowman

Jon,

Your description sounds like what I'm seeing, so I think you're right.

Thanks again,

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top