Change values in SafeArray

  • Thread starter Thread starter Steven Blair
  • Start date Start date
S

Steven Blair

I have some C++ code which creates a SafeArray and passes it to my C#
dll using COM:

SAFEARRAY *psaOut = SafeArrayCreateVector(VT_BSTR, 0, 3);

VARIANT pVarOut;
VariantInit(&pVarOut);
pVarOut.vt = VT_ARRAY | VT_BSTR;
pVarOut.parray = psaOut;

InvokeHelper(DispId, DISPATCH_METHOD, VT_I4, (void*)&result, parms,
&pVarIn, &pVarOut);

My C# code can see this fine. However, if I change an element of the
array, it isnt reflected when I return.

My question is, is my C# method signature the problem:

[Out,MarshalAs(UnmanagedType.SafeArray, SafeArraySubType =
VarEnum.VT_BSTR)] ref String[] OutputArray

I assume this is the correct signature for what I need to do, since I
can access the array with no problems.

Might be a tricky one, but any help would be appreciated.

Steven
 
Steven Blair said:
I have some C++ code which creates a SafeArray and passes it to my C#
dll using COM:

SAFEARRAY *psaOut = SafeArrayCreateVector(VT_BSTR, 0, 3);

VARIANT pVarOut;
VariantInit(&pVarOut);
pVarOut.vt = VT_ARRAY | VT_BSTR;
pVarOut.parray = psaOut;

InvokeHelper(DispId, DISPATCH_METHOD, VT_I4, (void*)&result, parms,
&pVarIn, &pVarOut);

My C# code can see this fine. However, if I change an element of the
array, it isnt reflected when I return.

My question is, is my C# method signature the problem:

[Out,MarshalAs(UnmanagedType.SafeArray, SafeArraySubType =
VarEnum.VT_BSTR)] ref String[] OutputArray

I assume this is the correct signature for what I need to do, since I
can access the array with no problems.

Might be a tricky one, but any help would be appreciated.

Steven


You must pass the array by reference.
pVarOut.vt = VT_ARRAY|VT_BSTR|VT_BYREF;

Why are you using dispatch calls from C++, while early binding is perfectly
possible?

Willy.
 
For the moment, I am returning the Array as a return value and that
works but I will try the VT_BYREF.
It shouldn't matter that we are passing an array of BSTR, I was begining
to wonder if I could only pass ints etc?

As for the approach for calling the methods, InvokeHelper is the only
way I know to be honest. Do you mean link the dll in statically and make
calls this way?

Thank you for the reply, was worried no one would.

Steven
 
Steven Blair said:
For the moment, I am returning the Array as a return value and that
works but I will try the VT_BYREF.
It shouldn't matter that we are passing an array of BSTR, I was begining
to wonder if I could only pass ints etc?

As for the approach for calling the methods, InvokeHelper is the only
way I know to be honest. Do you mean link the dll in statically and make
calls this way?

No, it's just a matter of using the COM support offered by the VC++
compiler.

Say you have a C# source file myAssembly, that declares/defines an interface
like this:

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("xxxxxxxxxxxxxxxxxxxxxxx")]
public interface IFoo
{
void Bar(ref string[] param);
}
After building and registering this assembly (see regasm /tlb ...), you will
find a typelib cthat can be imported in your C++ code.

#import ".\myAssembly.tlb" no_namespace named_guids raw_interfaces_only

above will tell the pre-compiler to build a header from the tlb which will
automatically be included by the C++ compiler.
This header file contains all you need to use early binding using smart
pointer support for your COM interface(s).

// Initialize the COM library first (calling CoInitialize or
CoInitializeEx)
...

HRESULT hr = 0;
IFooPtr pFoo;
// create and fill the safearray
SAFEARRAY * sa = ....;
hr = pFoo.CreateInstance(__uuidof(IFoo));
if(!FAILED(hr))
{
pFoo->Bar(&sa); // call Bar passing a reference to a SAFEARRAY of
BSTR
// access safearray returned by C#
...
}
...

Please search MSDN for more details on using "COM support in C++".


Willy.
 

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

Back
Top