Still need sample code for access to Win32 DLL

I

_iycrd

Specifically I need to wrap an older Win32 DLL in a managed class. I
had this running with VS2003's Managed Extensions, though it required
two separate classes.

With C++/CLI this was supposed to be simple, right? I had thought
that the new C++/CLI syntax was supposed to allow mixing of
managed/unmanaged in the same class but I'm running into quite a few
snags.

I'm sure the problems are commonplace, so rather than listing tons of
error messages, I'd like to get a good look at running sample code
that does this. Any leads?.
 
B

Bruno van Dooren

Specifically I need to wrap an older Win32 DLL in a managed class. I
had this running with VS2003's Managed Extensions, though it required
two separate classes.

With C++/CLI this was supposed to be simple, right? I had thought
that the new C++/CLI syntax was supposed to allow mixing of
managed/unmanaged in the same class but I'm running into quite a few
snags.

I'm sure the problems are commonplace, so rather than listing tons of
error messages, I'd like to get a good look at running sample code
that does this. Any leads?.

check out the thead 'Pointers and references VS2005' in this newsgroup,
dated 1 march.
Someone else had problems consuming a VC6 dll in C++/CLI.

I posted a working example. maybe this can help you too?
www.codeproject.com could have something as well.

--

Kind regards,
Bruno.
(e-mail address removed)
Remove only "_nos_pam"
 
I

_iycrd

[re: Wrapping DLLs with C++/CLI]

check out the thead 'Pointers and references VS2005' in this newsgroup,
dated 1 march.
Someone else had problems consuming a VC6 dll in C++/CLI.
I posted a working example. maybe this can help you too?

Thanks for that, Bruno. That will help elsewhere, but in this case,
the error messages are generated by the 'ref class' wrapper.
www.codeproject.com could have something as well.

I couldn't find anything on Codeproject.

OK, here are some specifics:

The unmanaged DLL has a corresponding .H file with typedefs for custom
structs etc:

in typedef_header.h:

typedef struct {
void *Handle;
unsigned long ULong;
} CustomType;

Some of those custom datatypes need to be accessed by several wrapped
functions in the managed wrapper class, so they must be exposed.

in the main C++/CLI wrapperclass.cpp:

#include "typedef_header.h"

public ref class WrapperClass {
char *CharArray;
CustomType Data;
};

Compiler Error:
error C4368: cannot define 'CustomType' as a member
of managed 'WrapperClass': mixed types are not supported

No problem with char* CharArray, though I'm not sure how to keep it
pinned.

Again, this was workable in VS2003 Managed Extensions, but required
two wrapper classes (unmanaged wrapped by managed). I'd like to get
this condensed into one C++/CLI container class, but I'm not sure how
to contain the unmanaged structs.

I'm sure I'm missing the obvious, and this must be covered somewhere.
I just can't find references.
 
B

Bruno van Dooren

error C4368: cannot define 'CustomType' as a member
of managed 'WrapperClass': mixed types are not supported

I found the answer here:
http://msdn2.microsoft.com/en-us/library/xhfb39es.aspx

in C++/CLI you cannot embed native types in managed types, but you can use
pointers to them.

a solution for your problem could be to use a pointer for which you
dynamically allocate the space in your constructor, instead of embedding
your type directly. obviously you have to delete the pointer in the
destructor of your ref class.

--

Kind regards,
Bruno.
(e-mail address removed)
Remove only "_nos_pam"
 
I

iycrd

I found the answer here:
http://msdn2.microsoft.com/en-us/library/xhfb39es.aspx

in C++/CLI you cannot embed native types in managed types, but you can use
pointers to them.

a solution for your problem could be to use a pointer for which you
dynamically allocate the space in your constructor, instead of embedding
your type directly. obviously you have to delete the pointer in the
destructor of your ref class.

I was afraid you were going to say that, Bruno. <g> I had come to the
same conclusion but was hoping I was missing something. There are so
many of those custom types that it's probably not worthwhile to go
with the conventional C++/CLI approach at all.

The main point of the inner unmanaged wrapper class (in the old
Managed Extensions version) was to isolate the awkward data types.
Requiring allocs for all those tiny structs would make things worse
rather than better, and would leave the managed code interspersed with
allocs and frees.

I guess I'm back to something like the old Managed Extensions
approach. I still may be able to move forward a tiny bit. This time
I could use the /cli compile switch, with the inner wrapping class
flagged as #pragma unmanaged, isolating the handles and awkward data
types. I think that will remove some of the ugly Managed Extensions
__whatever, leaving the code close to native. The outer class could
be a straight 'ref class' in managed code, calling into the inner
native class.

This would still look like ME code though, and would require two
function calls to get through the managed/unmanaged wrappers to the
inner DLL. I've found that to be error-prone. Still better than a
zillion allocs and frees.

I was looking forward to C++/CLI coming into its own, but I guess I
can't make use of it.

Another related question: Is there any way to use different compile
flags (/cli vs /cli:blush:ld....) on different files in one project?
 
B

Bruno van Dooren

I was looking forward to C++/CLI coming into its own, but I guess I
can't make use of it.

For what it's worth, this topic came up in the newsgroup a couple of weeks
ago, and I seem to recall someone from the VC compiler team saying that the
reason it wasn't yet implemented was the underlying complexity.
It is possible that this will still be implemented in a later VC version.
Another related question: Is there any way to use different compile
flags (/cli vs /cli:blush:ld....) on different files in one project?

I just did a quick test: while it is possible to specify /clr:blush:ldSyntax for
StdAfx.cpp and /clr for main.cpp,
you get a lot of compilation errors so I don't think it will work.
An alternative would be to put all that interop stuff in one class lib that
you compile with oldSyntax, and then use that classlib in a C++/CLI project.

--

Kind regards,
Bruno.
(e-mail address removed)
Remove only "_nos_pam"
 
I

_iycrd

For what it's worth, this topic came up in the newsgroup a couple of weeks
ago, and I seem to recall someone from the VC compiler team saying that the
reason it wasn't yet implemented was the underlying complexity.
It is possible that this will still be implemented in a later VC version.

Now that I think about the implications, that would be tough. Still,
it leaves a problem with encapsulating complex native code.

The typedef'd data is the main trainwreck for me. I'll need to resort
to the old unmanaged-wrapper-inside-a-managed-wrapper routine that
was used with managed extensions.

Given that the outer (managed) class will have to maintain a pointer
to the inner (unmanaged) class, a couple more questions arise:

Since the outer class has to create the unmanaged inner class, are
there any problems in the unmanaged code being affected by the memory
manager? I would think that simply doing this would work:

Class OuterClass {
private:
InnerClass * InnerPtr;
....
}

// Constructor
OuterClass::OuterClass()
{
InnerPtr = new InnerClass();
}

What, if anything, needs to be pinned? Is everything that's allloc'd
via 'new' safe from the memory manager? I have to make sure that
everything in the inner class stays put.
 
B

Bruno van Dooren

Since the outer class has to create the unmanaged inner class, are
there any problems in the unmanaged code being affected by the memory
manager? I would think that simply doing this would work:

Class OuterClass {
private:
InnerClass * InnerPtr;
....
}

// Constructor
OuterClass::OuterClass()
{
InnerPtr = new InnerClass();
}

What, if anything, needs to be pinned? Is everything that's allloc'd
via 'new' safe from the memory manager? I have to make sure that
everything in the inner class stays put.

I don't think anything should be pinned at all.
the fact that you use new (at least in C++/CLI) makes that InnerClass is
allocated on the normal heap.
the only thing that is managed is the pointer variable itself.

I.e. if you want to use &InnerClass in an unmanaged function you need to to
something like

UnManagedUseHandle(InnerClass ** InnerHandle); //example function
pin_ptr<InnerClass*> handle = &InnerPtr; //ping ptr
to ptr
UnManagedUseHandle(handle); //use ptr
to ptr

--

Kind regards,
Bruno.
(e-mail address removed)
Remove only "_nos_pam"
 
I

_iycrd

I don't think anything should be pinned at all.
the fact that you use new (at least in C++/CLI) makes that InnerClass is
allocated on the normal heap.

That's what I thought, but the memory manager makes me nervous about
that. <g> I wanted to make sure I hadn't misssed anything.

Bruno, you're a one-man team. Thanks for following up.
 

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