PInvoke a legacy class?

P

Peter Foot [MVP]

You can P/Invoke to C++ functions with decorated names only if they are
static functions, if they are instance members you can't, because
instantiating a C++ class from managed code is not possible.

If the functions are static, your only hurdle is to include the EntryPoint
property of the DllImport attribute to the full mangled name of the method /
or the numeric ordinal - you can use dumpbin or depends to find out this
information.

You could write a native C++ dll which would expose a single method which
created the class, called the method and then called the destructor, you can
then P/Invoke this from managed code.

Peter

--
Peter Foot
Windows Embedded MVP
www.inthehand.com | www.opennetcf.org

Do have an opinion on the effectiveness of Microsoft Windows Mobile and
Embedded newsgroups? Let us know!
https://www.windowsembeddedeval.com/community/newsgroups
 
T

Tim Johnson

I've read up on how to use P/Invoke to work with unmanaged legacy dlls with
a flat API. But how do you do that for a legacy dll that is built as a set
of classes? If I do a dumpbin of the dll I get decorated names which
include the class name as well as the method name. But I can't determine
from that the right syntax for the DllImport expression in my C# program.

For example, for a dll that exports a class XXX with a constructor,
destructor, and 1 method named Foo a normal C++ program could call things
like this:

XXX:XXX();
XXX:~XXX();
int XXX:Foo(int i);

But how/what to invoke from C# with P/Invoke - what's the right signature
for the DllImport attribute?
 
T

Tim Johnson

Thanks for the info. But how do I come up with the right full mangled name
from a dumpbin output? For example the "void Disconnect();" method of my
CStack class is reported as:

18 11 000052BC ?Disconnect@CStack@@QAAXXZ

Which parts actually constitute the mangled name DllImport is looking for?
--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625
 
A

Alex Feinman [MVP]

[DllImport("yourdll.dll", EntryPoint="?Disconnect@CStack@@QAAXXZ")]
extern static public Disconnect(...)

Now the problem is that this is a class member (CStack::Disconnect), so the
first parameter will be the expected to be CStack* (implicit this pointer),
which you have to provide as Peter points out
 
A

Alex Feinman [MVP]

Also notice that you will need to declare all methods you are going to
PInvoke as WINAPI (__stdcall) and the you will still need a C++ wrapper to
call constructors and destructors, since those always use thiscall
conventions and cannot be pinvoked directly

--
Alex Feinman
---
Visit http://www.opennetcf.org
Alex Feinman said:
[DllImport("yourdll.dll", EntryPoint="?Disconnect@CStack@@QAAXXZ")]
extern static public Disconnect(...)

Now the problem is that this is a class member (CStack::Disconnect), so
the first parameter will be the expected to be CStack* (implicit this
pointer), which you have to provide as Peter points out

--
Alex Feinman
---
Visit http://www.opennetcf.org
Tim Johnson said:
Thanks for the info. But how do I come up with the right full mangled
name
from a dumpbin output? For example the "void Disconnect();" method of
my
CStack class is reported as:

18 11 000052BC ?Disconnect@CStack@@QAAXXZ

Which parts actually constitute the mangled name DllImport is looking
for?
--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625
 
C

Chris Tacke, eMVP

Or create a class factory shim that creates the object and returns a
reference to it, then use that reference for all other method calls. Lots
of room there for memory leaks!

-Chris
 
T

Tim Johnson

I've gotten some other info too that I could write a managed C++ app that
basically mimiced my classes and wrapped my legacy DLL - is that what you
mean by a class factory? Or would managed C++ have the same problem, ie how
does it call down to the legacy classes/methods if not via PInvoke?

--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625
 
C

Chris Tacke, eMVP

No, it must be native. You'd have a method called CreateMyClass that
returned an instance handle to a class object. As Alex said, all class
methods take a class pointer as the implicit first parameter, so you'd pass
your instance handle for that.

-Chris
 
P

Paul G. Tobey [eMVP]

As Chris said, but, also, you can't used managed C++ with the .NET CF. The
run-time doesn't support it.

Paul T.
 
T

Tim Johnson

Didn't know that one! I'd only heard CF doesn't support COM interop. One
more CE incompatibility for the books. Thanks.

--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625
 
C

Chris Tacke, eMVP

The lack of support for managed C++ is well documented. The *only* managed
languages supported are VB and C#, so J# is also out (as well as COBOL,
FORTRAN and any other wackiness).

-Chris
 

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