PC Review


Reply
Thread Tools Rate Thread

C# access to C DLL

 
 
_BNC
Guest
Posts: n/a
 
      10th Jan 2005
Here's the breakdown:

I have an old C DLL that I want to access via C#.

I'm doing this via an outer DLL that wraps the old C DLL in an unmanaged
C++ class, which is in turn wrapped in a Managed C++ class. Both these
unmanaged C++ and managed C++ classes are compiled into a single assembly
(DLL) that is accessed by C#.

[C DLL] <--> [Unmanaged C++ / Managed C++] <--> [C# app]
old dll new C++ assembly app

I don't want to use standard Interop methods. I'm trying to do all the
direct access to the old C DLL with unmanaged C++. The data types in the
old C DLL are relatively complex, so I'm encapsulating the cluttered
legacy stuff in the new unmanaged C++ class.

IOW, I'll usually only be passing ints and a couple strings between the
unmanaged and managed sides.

In general, this approach works, but I'm getting occasional runtime errors
that I can't explain. Could someone post or refer me to a very simple
example that does this with even a single function? Say, take a function
from a stock Windows DLL and show a correct unmanaged C++ class
and managed C++ class that will wrap it correctly.

Thanks for any insights you can provide.


 
Reply With Quote
 
 
 
 
_BNC
Guest
Posts: n/a
 
      10th Jan 2005
On Sun, 09 Jan 2005 21:50:59 -0500, _BNC <_(E-Mail Removed)> wrote:

>Here's the breakdown:
>
>I have an old C DLL that I want to access via C#.
>
>I'm doing this via an outer DLL that wraps the old C DLL in an unmanaged
>C++ class, which is in turn wrapped in a Managed C++ class. Both these
>unmanaged C++ and managed C++ classes are compiled into a single assembly
>(DLL) that is accessed by C#.
>
> [C DLL] <--> [Unmanaged C++ / Managed C++] <--> [C# app]
> old dll new C++ assembly app
>
>I don't want to use standard Interop methods.


Oops. I meant I don't want to use PInvoke. I'm using the flat 'IJW'
model.

> I'm trying to do all the
>direct access to the old C DLL with unmanaged C++. The data types in the
>old C DLL are relatively complex, so I'm encapsulating the cluttered
>legacy stuff in the new unmanaged C++ class.
>
>IOW, I'll usually only be passing ints and a couple strings between the
>unmanaged and managed sides.
>
>In general, this approach works, but I'm getting occasional runtime errors
>that I can't explain. Could someone post or refer me to a very simple
>example that does this with even a single function? Say, take a function
>from a stock Windows DLL and show a correct unmanaged C++ class
>and managed C++ class that will wrap it correctly.
>
>Thanks for any insights you can provide.
>


 
Reply With Quote
 
Nicholas Paldino [.NET/C# MVP]
Guest
Posts: n/a
 
      10th Jan 2005
_BNC,

The example isn't going to be that complex, I am afraid. Actually, you
don't even need code to show how to call the C code from the unmanaged C++
code. The issue is properly handling the unmanaged C++ class (since it is
allocated on the unmanaged heap, etc, etc.).

Because your class will have an unmanaged resource in it (the unmanaged
C++ class), you should implement the IDispose interface, so that the Dispose
method can be exposed, and the class can be cleaned up correctly.

For more information on doing this sort of thing, check out the section
of the .NET framework titled "Managed Extensions for C++ Migration Guide",
located at (watch for line wrap):

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

Also, if you have time, and think that you can use the CLI extensions
(as managed extensions are going out the window), you might want to do that,
as it would be much easier, from what I hear.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (E-Mail Removed)



"_BNC" <_(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Sun, 09 Jan 2005 21:50:59 -0500, _BNC <_(E-Mail Removed)> wrote:
>
>>Here's the breakdown:
>>
>>I have an old C DLL that I want to access via C#.
>>
>>I'm doing this via an outer DLL that wraps the old C DLL in an unmanaged
>>C++ class, which is in turn wrapped in a Managed C++ class. Both these
>>unmanaged C++ and managed C++ classes are compiled into a single assembly
>>(DLL) that is accessed by C#.
>>
>> [C DLL] <--> [Unmanaged C++ / Managed C++] <--> [C# app]
>> old dll new C++ assembly app
>>
>>I don't want to use standard Interop methods.

>
> Oops. I meant I don't want to use PInvoke. I'm using the flat 'IJW'
> model.
>
>> I'm trying to do all the
>>direct access to the old C DLL with unmanaged C++. The data types in the
>>old C DLL are relatively complex, so I'm encapsulating the cluttered
>>legacy stuff in the new unmanaged C++ class.
>>
>>IOW, I'll usually only be passing ints and a couple strings between the
>>unmanaged and managed sides.
>>
>>In general, this approach works, but I'm getting occasional runtime errors
>>that I can't explain. Could someone post or refer me to a very simple
>>example that does this with even a single function? Say, take a function
>>from a stock Windows DLL and show a correct unmanaged C++ class
>>and managed C++ class that will wrap it correctly.
>>
>>Thanks for any insights you can provide.
>>

>



 
Reply With Quote
 
_BNC
Guest
Posts: n/a
 
      10th Jan 2005
[re 'flat model / C++ interop' bridge to unmanaged DLL]

On Mon, 10 Jan 2005 10:14:01 -0500, "Nicholas Paldino [.NET/C# MVP]"
<(E-Mail Removed)> wrote:

> The example isn't going to be that complex, I am afraid. Actually, you
>don't even need code to show how to call the C code from the unmanaged C++
>code. The issue is properly handling the unmanaged C++ class (since it is
>allocated on the unmanaged heap, etc, etc.).


> Because your class will have an unmanaged resource in it (the unmanaged
>C++ class), you should implement the IDispose interface, so that the Dispose
>method can be exposed, and the class can be cleaned up correctly.


I've done all unmanaged mem management (ahem) inside the unmanaged C++
wrapper. I haven't used 'dispose', as I manually keep track of all the
alloc'd memory. I don't think that's the problem, especially in that
there are only a couple large buffers that need to be accounted for. I'll
give that another look, but the code problems occur before the dealloc of
any objects.

The problem IS that the bridge between unmanaged and managed is somewhat
of a black box to me. I don't have time on this project to study the
Marshal class as thoroughly as I'd like, nor to review the sparse examples
that I've seen for 'flat model'. I'm afraid I'm missing something.

Despite that, the only thing I'm passing between managed/unmanaged is a
few pointers, and the code that I was drawing from did not use Marshal for
transfering simple (int, short) types.

The other puzzling thing is that failures are intermittent. It would seem
that (short of a sweep of the memory manager) they should either fail or
succeed. The failure rate seems independent of machine speed or amount of
available ram.

With enough study time and clues, I'd be able to solve this easily, but
unfortunately, the project manager doesn't have much patience for a
methodical approach.

> For more information on doing this sort of thing, check out the section
>of the .NET framework titled "Managed Extensions for C++ Migration Guide",
>located at (watch for line wrap):
>
>http://msdn.microsoft.com/library/de...nagedtypes.asp


Thanks for the pointer.

> Also, if you have time, and think that you can use the CLI extensions
>(as managed extensions are going out the window),


!? Uh-oh. I've done a search for CLI Extensions and come up with only a
handful of google hits. Is this part of VS 2005, or is it something that
is currently accessible?

Thanks, Nicholas.

B

 
Reply With Quote
 
Nicholas Paldino [.NET/C# MVP]
Guest
Posts: n/a
 
      10th Jan 2005
_BNC,

When I said that you would want to expose a Dispose method on the
managed end, it wasn't because of the memory management you use in the
unmanaged code, but for the class you use to wrap that code. Simply, if
your class has all the operations exposed as methods, then you are going to
create and store an instance of that class in the managed wrapper. You
should have a Dispose method on the managed wrapper so that it can dispose
of the unmanaged memory as soon as possible.

Now it could be argued that if you delete the unmanaged memory properly
in the finalizer, then the CLR will handle the memory management. However,
it isn't aware of the pressure that you place on the system to allocate that
class (or the buffers you manage), so it's probably better to expose an
IDisposable implementation.

If you are creating instances of these classes (using auto pointers) and
using them only in your methods, and not storing them on the class level,
then the IDisposable implementation is not needed.

As for CLI, check out the section of the Visual C++ Developers Center
titled "Translation Guide: Moving Your Programs from Managed Extensions for
C++ to C++/CLI", located at (watch for line wrap):

http://msdn.microsoft.com/visualc/wh...transguide.asp


--
- Nicholas Paldino [.NET/C# MVP]
- (E-Mail Removed)


"_BNC" <_(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> [re 'flat model / C++ interop' bridge to unmanaged DLL]
>
> On Mon, 10 Jan 2005 10:14:01 -0500, "Nicholas Paldino [.NET/C# MVP]"
> <(E-Mail Removed)> wrote:
>
>> The example isn't going to be that complex, I am afraid. Actually,
>> you
>>don't even need code to show how to call the C code from the unmanaged C++
>>code. The issue is properly handling the unmanaged C++ class (since it is
>>allocated on the unmanaged heap, etc, etc.).

>
>> Because your class will have an unmanaged resource in it (the
>> unmanaged
>>C++ class), you should implement the IDispose interface, so that the
>>Dispose
>>method can be exposed, and the class can be cleaned up correctly.

>
> I've done all unmanaged mem management (ahem) inside the unmanaged C++
> wrapper. I haven't used 'dispose', as I manually keep track of all the
> alloc'd memory. I don't think that's the problem, especially in that
> there are only a couple large buffers that need to be accounted for. I'll
> give that another look, but the code problems occur before the dealloc of
> any objects.
>
> The problem IS that the bridge between unmanaged and managed is somewhat
> of a black box to me. I don't have time on this project to study the
> Marshal class as thoroughly as I'd like, nor to review the sparse examples
> that I've seen for 'flat model'. I'm afraid I'm missing something.
>
> Despite that, the only thing I'm passing between managed/unmanaged is a
> few pointers, and the code that I was drawing from did not use Marshal for
> transfering simple (int, short) types.
>
> The other puzzling thing is that failures are intermittent. It would seem
> that (short of a sweep of the memory manager) they should either fail or
> succeed. The failure rate seems independent of machine speed or amount of
> available ram.
>
> With enough study time and clues, I'd be able to solve this easily, but
> unfortunately, the project manager doesn't have much patience for a
> methodical approach.
>
>> For more information on doing this sort of thing, check out the
>> section
>>of the .NET framework titled "Managed Extensions for C++ Migration Guide",
>>located at (watch for line wrap):
>>
>>http://msdn.microsoft.com/library/de...nagedtypes.asp

>
> Thanks for the pointer.
>
>> Also, if you have time, and think that you can use the CLI extensions
>>(as managed extensions are going out the window),

>
> !? Uh-oh. I've done a search for CLI Extensions and come up with only a
> handful of google hits. Is this part of VS 2005, or is it something that
> is currently accessible?
>
> Thanks, Nicholas.
>
> B
>



 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      10th Jan 2005
Can't help you if you don't show us some code (preferably a complete sample
that illustrates the problem) and/or more details about the run errors.
My guess is that you are passing un-pinned pointers to unmanaged code.

Willy.


"_BNC" <_(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Here's the breakdown:
>
> I have an old C DLL that I want to access via C#.
>
> I'm doing this via an outer DLL that wraps the old C DLL in an unmanaged
> C++ class, which is in turn wrapped in a Managed C++ class. Both these
> unmanaged C++ and managed C++ classes are compiled into a single assembly
> (DLL) that is accessed by C#.
>
> [C DLL] <--> [Unmanaged C++ / Managed C++] <--> [C# app]
> old dll new C++ assembly app
>
> I don't want to use standard Interop methods. I'm trying to do all the
> direct access to the old C DLL with unmanaged C++. The data types in the
> old C DLL are relatively complex, so I'm encapsulating the cluttered
> legacy stuff in the new unmanaged C++ class.
>
> IOW, I'll usually only be passing ints and a couple strings between the
> unmanaged and managed sides.
>
> In general, this approach works, but I'm getting occasional runtime errors
> that I can't explain. Could someone post or refer me to a very simple
> example that does this with even a single function? Say, take a function
> from a stock Windows DLL and show a correct unmanaged C++ class
> and managed C++ class that will wrap it correctly.
>
> Thanks for any insights you can provide.
>
>



 
Reply With Quote
 
_BNC
Guest
Posts: n/a
 
      11th Jan 2005
>> I'm doing this via an outer DLL that wraps the old C DLL in an unmanaged
>> C++ class, which is in turn wrapped in a Managed C++ class. Both these
>> unmanaged C++ and managed C++ classes are compiled into a single assembly
>> (DLL) that is accessed by C#.
>>
>> [C DLL] <--> [Unmanaged C++ / Managed C++] <--> [C# app]
>> old dll new C++ assembly app
>>
>> I don't want to use standard Interop methods. I'm trying to do all the
>> direct access to the old C DLL with unmanaged C++.


On Mon, 10 Jan 2005 21:49:06 +0100, "Willy Denoyette [MVP]"
<(E-Mail Removed)> wrote:

>Can't help you if you don't show us some code (preferably a complete sample
>that illustrates the problem) and/or more details about the run errors.
>My guess is that you are passing un-pinned pointers to unmanaged code.


Yeah, I was hoping that there was a simple code illustration somewhere.
I've seen many examples for PInvoke, but very little info on wrapping
unmanaged code, especially with both unmanaged and managed C++
classes in the same module. (Are there no code samples that do this?
I would have thought it was a common thing to do)

I will try to work up a simple example to post, but it will probably work
OK. The actual app is complex, and apparently only turns up problems
when stressed.

Still, your comment about pinning pointers may well be the main problem.

I've bought plenty of books on the subject (Grimes, Troelsen, etc) but as
I mentioned, my client won't afford the necessary time to dig into it (I
bet no one has heard that before). I believe it will take more more time
to NOT dig into the internals of this, but I don't have the luxury. I do
have a feeling that my initial reference example may have taken some
shortcuts.

Re pinning, a couple Q's come to mind:

Wouldn't pointer corruption only occur when the GC runs? Otherwise,
I can't imagine why a managed pointer would be altered.

How often does the garbage collector normally run on a medium-sized app?
(Presuming that lots of RAM is available)

Any recommended references that address this directly?

_B

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can't open my Access files after conversion from Access 97 to Access 2003 M Shafaat Microsoft Access 5 10th Apr 2010 09:04 PM
Saving Access 2007 database in Access 2003 format fails in Access =?Utf-8?B?U3Bpcm8=?= Microsoft Access External Data 0 13th Aug 2006 08:37 AM
W2K3 Service w/ UNC Access, Local Disk Access, and DB Access Rob Microsoft C# .NET 6 2nd Aug 2004 01:44 PM
Access "showing images on first page only of very wide Access report. Windows XP, Access XP Jack Microsoft Access Reports 4 18th Nov 2003 03:01 PM
Re: Allowing users (w/o MS Access) to access an Access 2000 database Wayne Morgan Microsoft Access 0 29th Sep 2003 11:46 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:48 PM.