473,786 Members | 2,304 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

SAFEARRAY* & COM Interop

I’ve got a C# library that I’ve built into a COM component that will be used
from a VC++ 6 application and while the creation of the COM object side of
things seem to be working fine, using the object fully is another matter.

On the C# side of things I’ve got an object defined like so:

[ClassInterface( ClassInterfaceT ype.None)]
public class PID : IPID
{
private string type;
private int number;
private PID[] pids;

public string Type
{
get { return type;}
set { type = value;}
}

public int Number
{
get { return number;}
set { number = value;}
}

public PID[] PIDs
{
get { return pids;}
set { pids = value;}
}

public PID(){}

public PID(string type, int number)
{
this.type = type;
this.number = number;
this.pids = new PID[0];
}

public PID(string type, int number, PID[] pids)
{
this.type = type;
this.number = number;
this.pids = pids;
}
}

I can instantiate an instance of this object in the MFC app with no
problem... the problem is when I try to set the PIDs array to... anything but
null really.

The issue is that the C# array is viewed by the MFC app as pointer to a
SAFEARRAY and all attempts to create an array of PID objects and assign them
to the PIDs property fails.

I’ve tried straight up (and cheesy) typecasting:

IPIDPtr pPID1(__uuidof( PID));
IPID *pid1 = pPID1;
....
IPID *pidArray1[2];
pidArray1[0] = pid2;
pidArray1[1] = pid3;
pid1->PIDs = (SAFEARRAY*)pid Array1;

Which causes a friendly “User breakpoint called from code at 0x7c901230” and
points to code I do not have the debug symbols for.

I also tried explicitly creating a SAFEARRAY with SafeArrayCreate :

SAFEARRAY * psa;
SAFEARRAYBOUND rgsabound[1];

rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;

psa = SafeArrayCreate (VT_VARIANT, 1, rgsabound);

LONG index = 0;
SafeArrayPutEle ment(psa, &index, &pid2);
index = 1;
SafeArrayPutEle ment(psa, &index, &pid3);

fi->PIDs = psa;

In this example everything works fine up until we assign PIDs (but not when
we set PIDs to null)... then we get an exception which reads:

Unhandled exception at 0x7c81eb33 in MFCWSTestApp.ex e: Microsoft C++
exception: _com_error @ 0x0012f8c4.

When the following line is called from the .tli wrapper:

inline void IFileInformatio n::PutPIDs ( SAFEARRAY * _arg1 ) {
_com_dispatch_m ethod(this, 0x60020004, DISPATCH_PROPER TYPUT,
VT_EMPTY, NULL,
L"\x2009", _arg1);
}

Thinking that I should be a little more explicit with regards to the size of
the elements (and based on another example) I tried the following:

SAFEARRAY *params = SafeArrayCreate Vector(VT_R4, 0, 2);

int paramMin = 0;

SafeArrayAccess Data(params, (void**)&pid1);
memcpy(&paramMi n, &pid1, sizeof(IPID));
SafeArrayUnacce ssData(params);

paramMin = 1;
SafeArrayAccess Data(params, (void**)&pid2);
memcpy(&paramMi n, &pid2, sizeof(PID));
SafeArrayUnacce ssData(params);

This test behaves similarly to the previous one in that the bulk of the code
executes without any error... but then an unhandled exception is thrown the
moment we try to assign PIDs to anything... including null:

Unhandled exception at 0x7c81eb33 in MFCWSTestApp.ex e: Microsoft C++
exception: _com_error @ 0x0012f894.

Because of the far easier to use environment and debugger I have spent a
fair amount of time trying to resolve this issue within the VC7.1
environment, unfortunately both VC6 and VC7 have the exact same issues with
the code in question.

Aside from the obvious issue of trying to use VC6... does anyone see what I
might be doing wrong here or have any ideas on how I could fix it?
Sep 18 '06 #1
1 6016
Hi Brendan,

see inline

"Brendan Grant" <gr****@NOSPAMd ahat.comwrote in message
news:F5******** *************** ***********@mic rosoft.com...
I've got a C# library that I've built into a COM component that will be
used
from a VC++ 6 application and while the creation of the COM object side of
things seem to be working fine, using the object fully is another matter.

On the C# side of things I've got an object defined like so:

[ClassInterface( ClassInterfaceT ype.None)]
public class PID : IPID
{
<snip/>
private PID[] pids;
<snip/>
public PID[] PIDs
{
get { return pids;}
set { pids = value;}
}
What does the COM declaration in C++ code look like? Have a look at your tlh
file. Is the retval a VARIANT* or a SAFEARRAY* ?
What is the definition of the interface IPID?
What do you expect to return there anyways? You have a class PID which
exposes an array of PID instances, each exposing a PID array again?
I am astonished that you can return a PID[]? To my knowledge you cannot
expose a class as parameter type, just an interface. Is it really PID[] or
IPID[] what you are returning?

<snip/>
>
I can instantiate an instance of this object in the MFC app with no
problem... the problem is when I try to set the PIDs array to... anything
but
null really.

The issue is that the C# array is viewed by the MFC app as pointer to a
SAFEARRAY and all attempts to create an array of PID objects and assign
them
to the PIDs property fails.

I've tried straight up (and cheesy) typecasting:

IPIDPtr pPID1(__uuidof( PID));
IPID *pid1 = pPID1;
When you take a raw interface pointer you should call AddRef and Release.
You get a little help here because pPID1 is a smartpointer so for its
lifetime pid1 is valid also. So why not you pPID1 directly and remove pid1.
...
IPID *pidArray1[2];
pidArray1[0] = pid2;
pidArray1[1] = pid3;
pid1->PIDs = (SAFEARRAY*)pid Array1;
What is pid1 and pid2? Have they been initialized?
Which causes a friendly "User breakpoint called from code at 0x7c901230"
and
points to code I do not have the debug symbols for.

I also tried explicitly creating a SAFEARRAY with SafeArrayCreate :

SAFEARRAY * psa;
SAFEARRAYBOUND rgsabound[1];

rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;

psa = SafeArrayCreate (VT_VARIANT, 1, rgsabound);

LONG index = 0;
SafeArrayPutEle ment(psa, &index, &pid2);
index = 1;
SafeArrayPutEle ment(psa, &index, &pid3);
This looks the most promising. But you made some small mistakes:
I guess pid2 and pid3 are of type IPID*, correct? If so you must not use &,
just pass pid2 and pid3 as they are already pointers so they are valid for
void*.
BUT: void* ist used because you have absolutely no type safety. The compiler
trusts you, and infect you lied to him ;)
You said: I want a safearray of VARIANTs. And later on you when you should
pass a VARIANT through void* you put an IPID* in there.
I guess you should setup two VARIANTs where you set the type to VT_UNKNOWN
and set punkVal to pid2 and pid3.

VARIANT v1, v2;
v1.vt = v2.vt = VT_UNKNOWN;
v1.punkVal = pid2; // I assume pid2 is AddReffed and you no longer use pid2
later on, so you transfer ownership to v1.
v2.punkVal = pid3; // same assumption

Now you call:
SafeArrayPutEle ments(psa, &index, &v1); // same for v2
fi->PIDs = psa;

In this example everything works fine up until we assign PIDs (but not
when
we set PIDs to null)... then we get an exception which reads:

Unhandled exception at 0x7c81eb33 in MFCWSTestApp.ex e: Microsoft C++
exception: _com_error @ 0x0012f8c4.

When the following line is called from the .tli wrapper:

inline void IFileInformatio n::PutPIDs ( SAFEARRAY * _arg1 ) {
_com_dispatch_m ethod(this, 0x60020004, DISPATCH_PROPER TYPUT,
VT_EMPTY, NULL,
L"\x2009", _arg1);
}
How comes IFileInformatio n into play? I thought we were using IPID?
>

Thinking that I should be a little more explicit with regards to the size
of
the elements (and based on another example) I tried the following:

SAFEARRAY *params = SafeArrayCreate Vector(VT_R4, 0, 2);
Why do you create an array of doubles when you want to store interface
pointers?
>
int paramMin = 0;

SafeArrayAccess Data(params, (void**)&pid1);
memcpy(&paramMi n, &pid1, sizeof(IPID));
SafeArrayUnacce ssData(params);

paramMin = 1;
SafeArrayAccess Data(params, (void**)&pid2);
memcpy(&paramMi n, &pid2, sizeof(PID));
SafeArrayUnacce ssData(params);
Why do you copy values 0 and 1 at the adresses of pid1 and pid2. What type
are pid1 and pid2?
This test behaves similarly to the previous one in that the bulk of the
code
executes without any error... but then an unhandled exception is thrown
the
moment we try to assign PIDs to anything... including null:

Unhandled exception at 0x7c81eb33 in MFCWSTestApp.ex e: Microsoft C++
exception: _com_error @ 0x0012f894.

Because of the far easier to use environment and debugger I have spent a
fair amount of time trying to resolve this issue within the VC7.1
environment, unfortunately both VC6 and VC7 have the exact same issues
with
the code in question.

Aside from the obvious issue of trying to use VC6... does anyone see what
I
might be doing wrong here or have any ideas on how I could fix it?
--
SvenC
Sep 18 '06 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1680
by: mic | last post by:
I'm stuck with following problem. Using webbrowser control I try to make custom-made request. I found working example of this written in VBS but porting it to Python doesn't seem to work. The key is navigate (or navigate2) method, that accepts PostData as one of it's parameters. As stated in reference: "The post data specified by PostData is passed as a SAFEARRAY Data Type structure. The variant should be of type Array and point to a...
4
10324
by: Roland Moschel | last post by:
Hi there ! I have some Problems to get a SafeArray out of a COM Server written in (Unmanaged) C++. From (unmanaged) Visual Basic , everything is ok , but unfortunately in C# I get an exception. Can anybody help me ?
1
2166
by: Doug Taylor | last post by:
How do I write the C# equivalent of the following VC6 methods? They will be exposed on a COM interface and used by VC6, VB6, and .NET apps. int SetPolygon(SAFEARRAY(double)points); int SetRectangle(SAFEARRAY(double)rects_info); int SetManyPolygons(SAFEARRAY(SAFEARRAY(double))points); Each point is an x/y pair. Each rects_info is an origin x/y, width, and height. --
5
6927
by: Tronster Hartley | last post by:
I've written an ATL 7.1 component and have a C# 1.1 client that is consuming it. The ATL component has a method with a that returns a SAFEARRAY of INTs, but my C# component chokes on it. The C# code: // Display a message box with a value from the ATL control private void GoButton_Click(object sender, System.EventArgs e) {
5
3111
by: Ahmad Jalil Qarshi | last post by:
i want to store binary data into my property. i read earlier positing on "microsoft.public.dotnet.languages.vc" group with subject as SAFEARRAY in attributed ATL7 Project. i followed the same approach but unfortunately i failed to do that. i declared the property accessors as follow in my idl file. HRESULT Data( SAFEARRAY * *pVal); HRESULT Data( SAFEARRAY * newVal); when i compile code i get following error.
5
6350
by: Maxim | last post by:
Hi all, I'm calling a COM Interface method that returnes SafeArray wrapped into variant. Is it possible to convert it to managed array? Because working with SAFEARRAY directly is a bit complicated. Or maybe there is a managed wrapper class for safe array? Thanks in advance.
1
2833
by: Christian Schmidt | last post by:
Hi all, I need to implement an unmanaged function that gets a SafeArray and hands it over to a managed function having the managed array-type. Using MarshalAs I can call unmanaged functions having SafeArray from managed code. But here I need this vice-versa... I assume it is doable with MarshalAs magic, but how? Thanks Christian
4
6551
by: Steven Blair | last post by:
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;
0
3225
skeptics
by: skeptics | last post by:
Trying to pass a SafeArray that i get form Request.BinaryRead Method in classic asp to a c# com interop component. In this thread i found a solution to pass and cast a normal asp safearray in to a c# array: http://bytes.com/groups/net/114755-passing-safearray-bytes-vbscript-managed-com-object-c#goto_threadtools but no matter what i try. i cant pass a array that i get from Request.BinaryRead Method in to the component. i always get a error...
0
9491
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10357
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10163
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9959
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8988
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing, and deploymentwithout human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7510
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupr who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5532
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4063
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3668
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.