473,769 Members | 2,382 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

create a wrapped managed dll that can be used from pure unmanagedcode

Hello,

I am trying to create a dll that internally uses managed types but
exposes a plain unmanaged interface. All the managed stuff shall be
"wrapped out of sight". So that I would be able to use that dll from
pure unmanaged code (for example inherit from classes in that dll). Is
something like that possible. I heared something called ManWarp tried
that approach.

If it is possible, how can I do that. Maybe there is a small litttle
sample project around ?
Nov 17 '05 #1
13 5054
You cannot use Managed classes from pure managed code unless they are
exposed to unmanaged code via COM interop

----------------
-Atul, Sky Software http://www.ssware.com
Shell MegaPack For .Net & ActiveX
Windows Explorer GUI Controls
&
Quick-Launch Like Appbars, MSN/Office2003 Style Popups,
System Tray Icons and Shortcuts/Internet Shortcuts
----------------

"bonk" <sc************ ******@gmx.de> wrote in message
news:uL******** ********@TK2MSF TNGP14.phx.gbl. ..
Hello,

I am trying to create a dll that internally uses managed types but exposes
a plain unmanaged interface. All the managed stuff shall be "wrapped out
of sight". So that I would be able to use that dll from pure unmanaged
code (for example inherit from classes in that dll). Is something like
that possible. I heared something called ManWarp tried that approach.

If it is possible, how can I do that. Maybe there is a small litttle
sample project around ?

Nov 17 '05 #2
"bonk" <sc************ ******@gmx.de> wrote in message
news:uL******** ********@TK2MSF TNGP14.phx.gbl. ..
I am trying to create a dll that internally uses managed types but exposes
a plain unmanaged interface. All the managed stuff shall be "wrapped out
of sight". So that I would be able to use that dll from pure unmanaged
code (for example inherit from classes in that dll). Is something like
that possible. I heared something called ManWarp tried that approach.

If it is possible, how can I do that. Maybe there is a small litttle
sample project around ?


Yes, it's possible. The short answer to your question is "Use 'It just
Works'" (aka IJW)

See here

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

and here

http://msdn.microsoft.com/msdnmag/is...5/default.aspx

for the details.

In case you don't know Managed C++ (aka MC++ soon to be renamed C++/CLI) is
the only CLS compliant language out of MS that allows you to mix managed and
unmanaged code in the same executable component or even the same module. So
what you can do is write unmanaged (native) code which calls into managed
code.

You can use

#pragma managed

and

#pragma unmanaged

delimiters to mark the stretches of code that are native and those that are
not. When a native function calls into a managed one, the compiler handles
the thunking necessary to make the transition.

That said, there are "issues" with mixed-mode DLLs that you must be aware
of. See here for the details.

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

If you can wait the two weeks till VS2005 is released, and if you can target
..Net v2.0 exclusively, you may have an easier time of it.

Regards,
Will


Nov 17 '05 #3
William DePalo [MVP VC++] schrieb:
"bonk" <sc************ ******@gmx.de> wrote in message
news:uL******** ********@TK2MSF TNGP14.phx.gbl. ..
I am trying to create a dll that internally uses managed types but exposes
a plain unmanaged interface. All the managed stuff shall be "wrapped out
of sight". So that I would be able to use that dll from pure unmanaged
code (for example inherit from classes in that dll). Is something like
that possible. I heared something called ManWarp tried that approach.

If it is possible, how can I do that. Maybe there is a small litttle
sample project around ?

Yes, it's possible. The short answer to your question is "Use 'It just
Works'" (aka IJW)

See here

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

and here

http://msdn.microsoft.com/msdnmag/is...5/default.aspx

for the details.

In case you don't know Managed C++ (aka MC++ soon to be renamed C++/CLI) is
the only CLS compliant language out of MS that allows you to mix managed and
unmanaged code in the same executable component or even the same module. So
what you can do is write unmanaged (native) code which calls into managed
code.

You can use

#pragma managed

and

#pragma unmanaged

delimiters to mark the stretches of code that are native and those that are
not. When a native function calls into a managed one, the compiler handles
the thunking necessary to make the transition.

That said, there are "issues" with mixed-mode DLLs that you must be aware
of. See here for the details.

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

If you can wait the two weeks till VS2005 is released, and if you can target
.Net v2.0 exclusively, you may have an easier time of it.

Regards,
Will


I like your answer better than the One from Atul. Thx. I will look into
it right away. Yes we can target .net 2.0 exclusively and yes we will
use vs 2005. I am working with c++/CLI and vs 2005 beta 2 right now.

Will,

there is one thing I still cannot understand. It has to do with how to
wrap the managed stuff away in that dll. You say I would "write
unmanaged (native) code which calls into managed code" and some of those
unmanaged classes that call into managed code will be exposed using
__declspec(dlle xport) correct? If so those unmanaged wrapper classes
will need to hold some private members to the managed classes
(gcroot <ManagedType^ > m_mythingy) and I will need to declare it as such
in the header. When I want to use the dll (with its lib) from another
plain unmanaged project I will need to include the header for it and it
will now have gcroot <ManagedType^ > m_mythingy; somewhere in the class
declaration. Wich is not possible since my project does not have /clr.
How am I supposed to wrap that away ?
Nov 17 '05 #4
bonk wrote:
When I want to use the dll (with its lib) from another
plain unmanaged project I will need to include the header for it and it
will now have gcroot <ManagedType^ > m_mythingy; somewhere in the class
declaration. Wich is not possible since my project does not have /clr.
How am I supposed to wrap that away ?


The same way as you would implement plugins: abstract virtual classes.
The client will call your DLL via an interface, which consists of a
bunch of virtual functions:

class MyInterface
{
public:
virtual void DoThis() = 0;
virtual void DoThat() = 0;
};

Inside the mixed-mode DLL you will inherit from this interface:

#pragma unmanaged
class MyImpl : public MyInterface
{
public:
MyImpl() : m_mythingy(gcne w [...])
~MyImpl() { delete m_mythingy; }

virtual void DoThis() { m_mything->DoThis(); }
virtual void DoThat() { m_mything->DoThat(); }

private:
gcroot<ManagedT ype^> m_mythingy;
};

Now all you have to do is export a function that creates an instance of
your impl:

__declspec(dlle xport) MyInterface* Create()
{
return new MyImpl();
}

As far as deleting the returned pointer, you can either export another
function called Delete:

__declspec(dlle xport) void Create(MyInterf ace* pimpl)
{
delete pimpl;
}

or simply add

virtual void DeleteMe() = 0

to the interface and

virtual void DeleteMe()
{
delete this;
}

to the impl. Then your client code would just do this:

MyInterface* p = Create();
p->DoThis();
p->DoThat();
p->DeleteMe();

This is the concept behind it. You don't even export MyImpl, and
MyInterface is just a header file that both the DLL and the client will
understand, as it's native C++.

Tom
Nov 17 '05 #5
Tamas Demjen wrote:
__declspec(dlle xport) void Create(MyInterf ace* pimpl)
{
delete pimpl;
}


I meant to call this function Delete. I should have also declared a
virtual destructor for MyInterface, that's pretty important, I missed
that originally.

I noticed that you also wanted to implement inheritance at the client
side. The problem is that you can't inherit from MyImpl, because it's
not visible to the client. So you have to add one more level of indirection:

class MyClass
{
public:
MyClass() : pimpl(Create()) { }
virtual ~MyClass() { pimpl->DeleteMe(); }
void DoThis() { pimpl->DoThis(); }
virtual void DoThat() { pimpl->DoThat(); }
private:
MyInterface* pimpl;
};

I chose to declare DoThis non-virtual and DoThat virtual. Note that in
MyInterface you are forced to declare everything virtual, whether you
actually want polymorphism or not -- that's the nature of the abstract
class-based plugin architecture. However, in MyClass, you should only
declare functions virtual is you actually want polymorphism. MyClass is
the base that's the native wrapper around the ManagedType. MyInterface
and MyImpl shouldn't even be used directly, they're just introduced as
an inter-module communication interface, which marshals the calls
between native and managed.

If you need to pass complicated managed types to ManagedType, such as
String^ or cli::array<What ever^>, then you have to marshal those on your
own, item by item. Alternatively, if you want to make a native STL
container available to .NET without copying/marshaling it, you can wrap
it into IEnumerable. The other way around, if you want to make a .NET
container available to native C++, you can use the exact same technique
that we used for wrapping MyManaged into MyClass.

The down side is that it requires a lot of typing, a lot of tedious,
manual labor. Also, every call goes through two levels of abstraction,
so it adds a minimal overhead to your code. I can imagine that P/Invoke
would add roughly the same amount of overhead too.

Tom
Nov 17 '05 #6
"bonk" <sc************ ******@gmx.de> wrote in message
news:%2******** ********@tk2msf tngp13.phx.gbl. ..
I like your answer better than the One from Atul.
We aim to please. :-)
Thx.
You are welcome.
I will look into it right away. Yes we can target .net 2.0 exclusively and
yes we will use vs 2005. I am working with c++/CLI and vs 2005 beta 2
right now.
Then you are a few steps ahead of me. I hear that the mixed-mode interop
story is significantly better with C++/CLI and .Net 2.0 but I have had no
time to experiment with it.
there is one thing I still cannot understand. It has to do with how to
wrap the managed stuff away in that dll. You say I would "write unmanaged
(native) code which calls into managed code" and some of those unmanaged
classes that call into managed code will be exposed using
__declspec(dlle xport) correct?
This is always problematic. Exporting a class based interface from a DLL
where you explicitly export the methods by name is usually only possible in
an environment where all DLL clients use the same compiler. I see that Tom
has already proposed one approach.
If so those unmanaged wrapper classes will need to hold some private
members to the managed classes
(gcroot <ManagedType^ > m_mythingy) and I will need to declare it as such
in the header. When I want to use the dll (with its lib) from another
plain unmanaged project I will need to include the header for it and it
will now have gcroot <ManagedType^ > m_mythingy; somewhere in the class
declaration. Wich is not possible since my project does not have /clr. How
am I supposed to wrap that away ?


Well, my MVP buds may slap me on the wrist for this, but one thing you can
do is eschew the gcroot template class, use the managed class GCHandle
(garabage collector handle) directly - which is what gcroot does - and cast
that handle to an integer. Of course, all type information is "lost" when
you do that, and later when you cast from integer back to managed type you
better cast correctly or _very_ bad things will happen. :-)

I should tell you that I started to put this reply together before Tom
posted his, had dinner, and saw Tom's reply. Feel free to ignore it. But
since it took me more than 30 minutes to test and debug, I thought I'd post
it in its entirety. :-)

First, I used this C# class to create an assemby: ClassLibrary1

//------------------------------------------------------------
using System;
using System.Runtime. InteropServices ;

namespace ClassLibrary1
{
public class Class1
{
public Class1()
{
}

public void SayHello()
{
Console.WriteLi ne("C# says hello!");
}
}
}
//------------------------------------------------------------

Then I created a DLL which defines a unmanaged class that proxies the
managed class: ClassLibrary1Sh im

Note that I took the expedient approach of exporting an unmanaged procedural
function. Exporting the shim class is left as an exercise to the interested
reader. :-) What I've done here is admittedly not very elegant, but it is
very simple. The implemention of every method in the shim class starts out
as unmanaged code and uses IJW to complete the job in managed code. Note
that the shim class stores the garbage collector's handle to the instance of
the managed class as an integer. OK, it's a hack.

Note that you must follow the rules here to build a mixed-mode DLL.

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

//------------------------------------------------------------
using <mscorlib.dll >

using namespace System;
using namespace System::Runtime ::InteropServic es;
using namespace ClassLibrary1;

#pragma managed

int Allocator()
{
GCHandle gch;
Class1 __gc *cl1;

cl1 = new ClassLibrary1:: Class1();
gch = GCHandle::Alloc (cl1);
return GCHandle::op_Ex plicit(gch).ToI nt32();
}

void Deallocator(int h)
{
GCHandle gch;

gch = GCHandle::op_Ex plicit(h);
gch.Free();
}

void SayHello(int h)
{
GCHandle gch;
Class1 __gc *cl1;

gch = GCHandle::op_Ex plicit(h);
cl1 = dynamic_cast<Cl ass1 *>( gch.get_Target( ) );

cl1->SayHello();
}

#pragma unmanaged

class NativeClassLibr ary1
{
private:

int h;

public:

NativeClassLibr ary1();
~NativeClassLib rary1();
void SayHello();
};

NativeClassLibr ary1::NativeCla ssLibrary1()
{
h = ::Allocator();
}

NativeClassLibr ary1::~NativeCl assLibrary1()
{
::Deallocator(h );
}

void NativeClassLibr ary1::SayHello( )
{
::SayHello(h);
}

void __stdcall TheUmanagedExpo rtFunction()
{
NativeClassLibr ary1 ncl1;

ncl1.SayHello() ;
}
//------------------------------------------------------------

I used this module defintion file to build the DLL above.
//------------------------------------------------------------
LIBRARY ClassLibrary1Sh im
EXPORTS

TheUmanagedExpo rtFunction

//------------------------------------------------------------

And this is the native executable I used to test the whole mess. Note that I
load the DLL manually only because I am terminally lazy with toy samples.

//------------------------------------------------------------
#include <windows.h>

int main()
{
FARPROC fp;
HINSTANCE h;

h = LoadLibrary("Cl assLibrary1Shim .dll");
fp = GetProcAddress( h, "TheUmanagedExp ortFunction");

(*fp)();

return 0;
}
//------------------------------------------------------------

Finally, I don't know what to make of this, but everything works well except
when I try to enable mixed-mode debugging. Then the IDE crashes. :-(

Regards,
Will




Nov 17 '05 #7
William DePalo [MVP VC++] wrote:
Well, my MVP buds may slap me on the wrist for this, but one thing you can
do is eschew the gcroot template class, use the managed class GCHandle
(garabage collector handle) directly - which is what gcroot does - and cast
that handle to an integer. Of course, all type information is "lost" when
you do that, and later when you cast from integer back to managed type you
better cast correctly or _very_ bad things will happen. :-)


That's an interesting idea. What if you do this:

#ifdef BUILDING_DLL
#define EXPORT_DLL __declspec(dlle xport)
#else
#define EXPORT_DLL __declspec(dlli mport)
#endif
class EXPORT_DLL Unmanaged
{
private:
#ifdef _MANAGED
gcroot<Managed^ > pimpl;
#else
void* not_your_busine ss;
#endif
};
// untested code ^^^

After all, the compiler only needs to know the size of the object for
instantiation. Since the pimpl member is private, descendants can't
access it anyway. As long as a dummy variable of the same size is
reserved there, we should be fine, theoretically.

Well, it was not my idea originally, so... I know it can bite. For
example, what if Microsoft changes the implementation of gcroot? But a
static assertion would help there, just in case:

#include <boost/static_assert.h pp>
BOOST_STATIC_AS SERT(sizeof(gcr oot<Managed^>) == sizeof(void*));
// untested code ^^^

Just an idea, I know it's a hack. Any comments? It's an interesting
discussion.

Tom
Nov 17 '05 #8
"Tamas Demjen" <td*****@yahoo. com> wrote in message
news:%2******** ********@TK2MSF TNGP15.phx.gbl. ..
William DePalo [MVP VC++] wrote:
Well, my MVP buds may slap me on the wrist for this, but one thing you
can do is eschew the gcroot template class, use the managed class
GCHandle (garabage collector handle) directly - which is what gcroot
does - and cast that handle to an integer. Of course, all type
information is "lost" when you do that, and later when you cast from
integer back to managed type you better cast correctly or _very_ bad
things will happen. :-)
That's an interesting idea. What if you do this:

#ifdef BUILDING_DLL
#define EXPORT_DLL __declspec(dlle xport)
#else
#define EXPORT_DLL __declspec(dlli mport)
#endif
class EXPORT_DLL Unmanaged
{
private:
#ifdef _MANAGED
gcroot<Managed^ > pimpl;
#else
void* not_your_busine ss;
#endif
};
// untested code ^^^

After all, the compiler only needs to know the size of the object for
instantiation. Since the pimpl member is private, descendants can't access
it anyway. As long as a dummy variable of the same size is reserved there,
we should be fine, theoretically.


Right. I think your idea is in line with Paul DiLascia's:

http://msdn.microsoft.com/msdnmag/issues/05/04/C/
Well, it was not my idea originally, so... I know it can bite.
Yup, but very little is guaranteed with software.
For example, what if Microsoft changes the implementation of gcroot? But a
static assertion would help there, just in case:

#include <boost/static_assert.h pp>
BOOST_STATIC_AS SERT(sizeof(gcr oot<Managed^>) == sizeof(void*));
// untested code ^^^

Just an idea, I know it's a hack. Any comments?
"Hack" is my middle name <g>. I used an int. P.DiL used an intptr_t. You use
a void*. To an old C guy like me, any old 32 bits will do. <gd&r>.
Seriously, I wonder if GC handles get widened to 64 bits on a 64 bit
platform?
It's an interesting discussion.


I completely agree. I've learned more than a little through the years
reading some of the groups I follow. And what is really surprising is that
sometimes I gain a deeper understanding of a point I am trying to make in
trying to explain it to someone who has no idea of what I am trying to
convey.

Regards,
Will
Nov 17 '05 #9
William DePalo [MVP VC++] wrote:
I used an int. P.DiL used an intptr_t. You use
a void*. To an old C guy like me, any old 32 bits will do. <gd&r>.
Seriously, I wonder if GC handles get widened to 64 bits on a 64 bit
platform?


That's exactly why void* (or any pointer, for that matter), is a better
choice than an int. I read that void* is 64 bits on Win64, while int is
only 32 bits. An int* would be perfect.

By the way, I just took a look at the implementation of gcroot, and it
has a single data member of type void*. That's the main reason I chose
void*, even without thinking of it. I just wanted to ensure that
sizeof(my_dummy _variable) = sizeof(gcroot<T ^>).

It would be nice to try with a sample app.

Cheers,
Tom
Nov 17 '05 #10

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

Similar topics

2
13411
by: brazilnut52 | last post by:
I am going to outline the steps I go through to produce the problem. Hopefully this will help you understand the problem better I have created a simple COM DLL in .NET by using the COM class template and by setting output to a type library (DLL). All the object does is return a string value. At this point I have not checked the option to register for COM interop in Visual Studio So I go into Excel (where I want to use the object). Go to VB...
1
741
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 managed point-of-view I've noticed that: 1) for each managed and unmanaged C function (not C++ classes) I get a public managed static method (defined on a 'Global Functions' class) in the generated assembly with an export name of the form...
5
1724
by: | last post by:
Is there a way to create pure old style DLL's? using C#? I need to use these DLL's in a VC 6 project that does not support managed code (as plugins) But the VC 6 code doesn't use Interfaces to that, just classic dll entry points.
1
1228
by: Kalafiorczyk | last post by:
Ladies and Gentlemen of Microsoft! I'm having a small problem that I hope to be able to solve without having to burn a support call included with MSDN. I have a short "Hello, world!" app that is 100% portable between Standard C++ and Managed C++. I can build it with VS7.1 using command line. But I cannot reproduce my results in the IDE.
8
4525
by: Ted Miller | last post by:
Hi folks, I'm looking at moving a large base of C++ code to .Net under tight time constraints. The code runs in mission-critical environments, and I am extremely concerned about the loader lock problem and the potential for deadlocks. After pouring over the available information, and trying a few experiments, I am still left with a few questions and issues I hope someone out there can shed some light on.
6
1461
by: nicolas.hilaire | last post by:
Hi all, i'm not totally clear with some concepts about managed and unmanaged code. I'm asking myself some questions : - i've a MFC app, i want to use the framework dotnet by switching to /clr compilation mode. Is my app in CLR, or only the call to the
2
1824
by: Haroon_Saeed | last post by:
Hey, I wrote a managed c++ class library in viusal studio 2005. This managed c++ dll calls native C++ methods of an SDK. When I referenced this managed c++ library in a console applciation written in C# for testing every thing worked fine. Now I need to call the managed c++ class library through web service written in C#. When I call managed c++ methods from web service the code crashes on the line from where the native code starts(...
5
7271
by: =?Utf-8?B?U2hhcm9u?= | last post by:
I have a class that is writen in unmanaged pure native C++. This class files (h and cpp) are inserted to a managed C++ (VC++ 2005, C++/CLI) DLL compoenet. This DLL compoenet is used in a C# application. My question is: Does the performance of the unmanaged pure native C++ class described above is the same if it was a in a pure unmanaged native C++ DLL component?
0
9586
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10210
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10043
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9861
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7406
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5298
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3561
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2814
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.