HighTechTalks DotNet Forums  

Passing Variant SafeArrays from C# into C++ DLL

Dotnet Framework (Interop) microsoft.public.dotnet.framework.interop


Discuss Passing Variant SafeArrays from C# into C++ DLL in the Dotnet Framework (Interop) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
praetor
 
Posts: n/a

Default Passing Variant SafeArrays from C# into C++ DLL - 04-21-2009 , 10:55 AM






I haven't found any comprehensive sample code on this topic. Lots of pages
cover C++ VARIANT and SAFEARRAYS, but nothing covering C# interoperability.

I need to consume an existing service in C++ using C#. Previous clients
used VB6 arrays. To paraphrase, I have a method in C++:

int __stdcall DoSomething( VARIANT *pvArray );

I have tried calling this method using the following:

TRIAL #1
[DllImport("binary.dll")]
private static extern DoSomething( ref [] object vArray );
(...)
Object [] variant;
System.Collections.ArrayList vP = new System.Collections.ArrayList();
vP.Add( (ulong)12345 );
variant = vP.ToArray();
CAScc_CompleteWorkVariant(m_hAgent, "101", 0, ref variant, "");

TRIAL #2
[DllImport("binary.dll")]
private static extern DoSomething( ref object vArray );
(...)
Object variant;
System.Collections.ArrayList vP = new System.Collections.ArrayList();
vP.Add( (ulong)12345 );
variant = vP.ToArray();
CAScc_CompleteWorkVariant(m_hAgent, "101", 0, ref variant, "");

TRIAL #3
[DllImport("binary.dll")]
private static extern DoSomething( ref object vArray );
(...)
Object variant;
System.Collections.ArrayList vP = new System.Collections.ArrayList();
vP.Add( (ulong)12345 );
variant = new VariantWrapper(vP.ToArray());
CAScc_CompleteWorkVariant(m_hAgent, "101", 0, ref variant, "");

I have tried a bunch of other stuff; but I have ommitted them for brevity.
Everytime I debug the C++, by variant pointer is ALWAYS null.

Are there any comprehensive samples out there on how to get something like
this done?

Thanks,

James
Beverly, MA



Reply With Quote
  #2  
Old   
Giovanni Dicanio
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 04-21-2009 , 06:34 PM







"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel messaggio
news:30787F61-C8F4-4650-957F-A4B6C7478D16 (AT) microsoft (DOT) com...

Quote:
I need to consume an existing service in C++ using C#. Previous clients
used VB6 arrays. To paraphrase, I have a method in C++:

int __stdcall DoSomething( VARIANT *pvArray );

I have tried calling this method using the following:
[...]
I have tried a bunch of other stuff; but I have ommitted them for brevity.
Everytime I debug the C++, by variant pointer is ALWAYS null.
I'm not sure what your VARIANT stores (a SAFEARRAY of VT_UI4 ?).
Moreover, is this VARIANT an input only parameter?

However, if you can't find the proper marshaling on the C# side, I would
suggest you to just write a C++/CLI bridging layer wrapper over your
original DoSomething().
e.g.

// in C++/CLI
int DoSomethingWrapper( array<UInt32>^ data )
{
... create a VARIANT to pass to DoSomething().
VARIANT var;
...
fill VARIANT with data stored in 'data' input variable
...

// Call your original DoSomething:
return DoSomething( &var );
}

You can call the DoSomethingWrapper() directly from C#, passing a simple C#
array to it.

HTH,
Giovanni



Reply With Quote
  #3  
Old   
praetor
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 04-22-2009 , 10:59 AM



I like your suggestion; but if it is not a managed DLL, would I need to do
any .NET library initialization?

In answer to your question,
It is a Variant SAFEARRAY of VARIANT SAFEARRAY's.
The inner array has two elements. One a uint, the other either a
String, Date, our Double. With this info, could you come up with a direct
signature?

Let me know,

James
Beverly, MA

"Giovanni Dicanio" wrote:

Quote:
"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel messaggio
news:30787F61-C8F4-4650-957F-A4B6C7478D16 (AT) microsoft (DOT) com...

I need to consume an existing service in C++ using C#. Previous clients
used VB6 arrays. To paraphrase, I have a method in C++:

int __stdcall DoSomething( VARIANT *pvArray );

I have tried calling this method using the following:
[...]
I have tried a bunch of other stuff; but I have ommitted them for brevity.
Everytime I debug the C++, by variant pointer is ALWAYS null.

I'm not sure what your VARIANT stores (a SAFEARRAY of VT_UI4 ?).
Moreover, is this VARIANT an input only parameter?

However, if you can't find the proper marshaling on the C# side, I would
suggest you to just write a C++/CLI bridging layer wrapper over your
original DoSomething().
e.g.

// in C++/CLI
int DoSomethingWrapper( array<UInt32>^ data )
{
... create a VARIANT to pass to DoSomething().
VARIANT var;
...
fill VARIANT with data stored in 'data' input variable
...

// Call your original DoSomething:
return DoSomething( &var );
}

You can call the DoSomethingWrapper() directly from C#, passing a simple C#
array to it.

HTH,
Giovanni



Reply With Quote
  #4  
Old   
Giovanni Dicanio
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 04-22-2009 , 11:36 AM




"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel messaggio
news56454AE-8F88-4DD0-B167-96C2DF8DCF59 (AT) microsoft (DOT) com...

Quote:
I like your suggestion; but if it is not a managed DLL, would I need to do
any .NET library initialization?
I don't understand this question well, i.e: I'm not sure I understand what
you mean by "do any .NET library initialization".

My suggestion is to build a C++/CLI class library that exposes methods to
wrap the native DLL exported functions:
Add New Project | Visual C++ | CLR | Class Library.

Then you can build the VARIANT in some method of the C++/CLI class, and pass
this VARIANT to the native DLL.

The C# client talks to the C++/CLI class directly (not to the native DLL;
the C++/CLI class talks to the native DLL).

Quote:
In answer to your question,
It is a Variant SAFEARRAY of VARIANT SAFEARRAY's.
The inner array has two elements. One a uint, the other either a
String, Date, our Double. With this info, could you come up with a direct
signature?
I think that if the native function uses a VARIANT * as parameter, the
corresponding C# signature should be 'ref object'.
There is also a class called VariantWrapper, but I'm not sure that it can
help you in this particular case:

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.variantwrapper.aspx

I still think that the simplest way would be to just use the C++/CLI
bridging technique, and build the VARIANT directly from C++/CLI.

HTH,
Giovanni



Reply With Quote
  #5  
Old   
praetor
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 04-23-2009 , 10:39 AM



I already have a dll. If I were to write this wrapper method, I would simply
add it to the existing binary. It gets released to customers/3rd parties; so
I don't want to add the burden of deploying an extra binary.

That said, my existing binary is not managed. Could I initialize the .NET
library dynamically in a non dotnet C++ dll? If so, how?

Thanks,

James
Beverly, MA

"Giovanni Dicanio" wrote:

Quote:
"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel messaggio
news56454AE-8F88-4DD0-B167-96C2DF8DCF59 (AT) microsoft (DOT) com...

I like your suggestion; but if it is not a managed DLL, would I need to do
any .NET library initialization?

I don't understand this question well, i.e: I'm not sure I understand what
you mean by "do any .NET library initialization".


Reply With Quote
  #6  
Old   
Giovanni Dicanio
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 04-24-2009 , 03:05 AM




"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel messaggio
newsEE45A57-4AEC-463B-8AF3-EC3F2721A71B (AT) microsoft (DOT) com...
Quote:
I already have a dll. If I were to write this wrapper method, I would
simply
add it to the existing binary. It gets released to customers/3rd parties;
so
I don't want to add the burden of deploying an extra binary.

That said, my existing binary is not managed. Could I initialize the .NET
library dynamically in a non dotnet C++ dll? If so, how?
I've never done a DLL that exposes both unmanaged code and managed code at
its public interface, but I think it is possible.
Of course, building a simple test project on Visual Studio would answer
that. You may want to try Add New Project | Visual C++ | CLR | Class Library
template, and then expose also pure C native functions.

Or, if you have an existing native DLL, you may want to go to Project
Properties | Configuration Properties | General and select "Common Language
Runtime Support (/clr)" in "Common Language Runtime support" field, and then
add C++/CLI code, e.g.

namespace TestLibNative {

public ref class SomeWrapperClass
{
public:
void DoSomething()
{
...
}
};
}


HTH,
Giovanni



Reply With Quote
  #7  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: Passing Variant SafeArrays from C# into C++ DLL - 05-13-2009 , 04:41 PM



praetor wrote:
Quote:
I already have a dll. If I were to write this wrapper method, I
would simply add it to the existing binary. It gets released to
I think that if you try that, your dll will take a dependency on mscoree and
it won't run anymore except in a .NET program. Maybe you can work around
that by marking the mscoree dependency as delayload. Definitely avoid
compiling your native entrypoints with /clr, if you want native clients to
be able to call them (this requires putting your managed wrapper in a
separate .cpp file, then combining managed code with purely native object
files at the link step).


Quote:
customers/3rd parties; so I don't want to add the burden of deploying
an extra binary.

That said, my existing binary is not managed. Could I initialize the
.NET library dynamically in a non dotnet C++ dll? If so, how?
You can't use .NET data types directly from native code, because the garbage
collector needs the metadata describing stack variables.

Quote:
Thanks,

James
Beverly, MA

"Giovanni Dicanio" wrote:


"praetor" <praetor (AT) discussions (DOT) microsoft.com> ha scritto nel
messaggio news56454AE-8F88-4DD0-B167-96C2DF8DCF59 (AT) microsoft (DOT) com...

I like your suggestion; but if it is not a managed DLL, would I
need to do any .NET library initialization?

I don't understand this question well, i.e: I'm not sure I
understand what you mean by "do any .NET library initialization".



Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.