Change values in SafeArray

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
 
W

Willy Denoyette [MVP]

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.
 
S

Steven Blair

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
 
W

Willy Denoyette [MVP]

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

Top