473,322 Members | 1,719 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Marshalling a SAFEARRAY from an ATL component into CS.

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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );

int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred
in Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );

c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );

c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );

return S_OK;
}
All of this code is from a sample application I'm just trying to prove
the concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.
Nov 17 '05 #1
5 6904
have you check out this page on MSDN:

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

HTH

Ollie Riches

"Tronster Hartley" <tr**************@thomson.com> wrote in message
news:uf*************@TK2MSFTNGP12.phx.gbl...
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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );
int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred in
Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
return S_OK;
}
All of this code is from a sample application I'm just trying to prove the
concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.

Nov 17 '05 #2
Please post your method declaration (midl).
I'm not clear how you declared your SAFEARRAY return argument, as far as I
know you can't return a safearray (retval)
Willy.

"Tronster Hartley" <tr**************@thomson.com> wrote in message
news:uf*************@TK2MSFTNGP12.phx.gbl...
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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );
int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred in
Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
return S_OK;
}
All of this code is from a sample application I'm just trying to prove the
concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.

Nov 17 '05 #3
You may be right in terms of SAFEARRAYs not able to be returned; the
MSDN article pointed to by Ollie Riches seems to show that an in or
in/out parameter is the only type that can be decorated for marshaling.
:( (I hope that isn't true.)


Below is the IDL:

import "oaidl.idl";
import "ocidl.idl";

[
uuid(0A15D60D-B87D-4B1C-AA85-07BF51CB6FF0),
version(1.0),
helpstring("SAServer 1.0 Type Library")
]
library SAServerLib
{
importlib("stdole2.tlb");
[
uuid(908FF2FF-CA80-4858-BD8D-89CFF5CAFEA3),
helpstring("_IbobEvents Interface")
]
dispinterface _IbobEvents
{
properties:
methods:
};

[
object,
uuid(1C4CD34D-8B6D-4571-B00A-4930FD1FFAF0),
dual,
nonextensible,
helpstring("Ibob Interface"),
pointer_default(unique)
]
interface Ibob : IDispatch{
[id(1), helpstring("method Populate")]
HRESULT Populate([out,retval] SAFEARRAY** saData);
};

[
uuid(D9C4E6D0-4A9F-4A8F-95EC-6ACACBACB67C),
helpstring("bob Class")
]
coclass bob
{
[default] interface Ibob;
[default, source] dispinterface _IbobEvents;
};
};

Willy Denoyette [MVP] wrote:
Please post your method declaration (midl).
I'm not clear how you declared your SAFEARRAY return argument, as far as I
know you can't return a safearray (retval)
Willy.

"Tronster Hartley" <tr**************@thomson.com> wrote in message
news:uf*************@TK2MSFTNGP12.phx.gbl...
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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );
int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred in
Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
return S_OK;
}
All of this code is from a sample application I'm just trying to prove the
concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.


Nov 17 '05 #4
Thank you Ollie.

I had not found that page in my searches. I'm gleaning information from
it now as I try to get this to work.

Cheers.
Ollie Riches wrote:
have you check out this page on MSDN:

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

HTH

Ollie Riches

"Tronster Hartley" <tr**************@thomson.com> wrote in message
news:uf*************@TK2MSFTNGP12.phx.gbl...
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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );
int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred in
Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
return S_OK;
}
All of this code is from a sample application I'm just trying to prove the
concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.


Nov 17 '05 #5
You should indicate the type of SAFEARRAY element, so your IDL should look
like this:

[id(1), helpstring("method Populate")] HRESULT Populate([out,
retval]SAFEARRAY(int)* psa);

STDMETHODIMP CBob::Populate(SAFEARRAY** psa)
{

As such in C#, you can return into an int[]

int[] ia = obj.Populate();

Willy.

Tronster Hartley" <tr**************@thomson.com> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
You may be right in terms of SAFEARRAYs not able to be returned; the MSDN
article pointed to by Ollie Riches seems to show that an in or in/out
parameter is the only type that can be decorated for marshaling. :( (I
hope that isn't true.)

Below is the IDL:

import "oaidl.idl";
import "ocidl.idl";

[
uuid(0A15D60D-B87D-4B1C-AA85-07BF51CB6FF0),
version(1.0),
helpstring("SAServer 1.0 Type Library")
]
library SAServerLib
{
importlib("stdole2.tlb");
[
uuid(908FF2FF-CA80-4858-BD8D-89CFF5CAFEA3),
helpstring("_IbobEvents Interface")
]
dispinterface _IbobEvents
{
properties:
methods:
};

[
object,
uuid(1C4CD34D-8B6D-4571-B00A-4930FD1FFAF0),
dual,
nonextensible,
helpstring("Ibob Interface"),
pointer_default(unique)
]
interface Ibob : IDispatch{
[id(1), helpstring("method Populate")]
HRESULT Populate([out,retval] SAFEARRAY** saData);
};

[
uuid(D9C4E6D0-4A9F-4A8F-95EC-6ACACBACB67C),
helpstring("bob Class")
]
coclass bob
{
[default] interface Ibob;
[default, source] dispinterface _IbobEvents;
};
};

Willy Denoyette [MVP] wrote:
Please post your method declaration (midl).
I'm not clear how you declared your SAFEARRAY return argument, as far as
I know you can't return a safearray (retval)
Willy.

"Tronster Hartley" <tr**************@thomson.com> wrote in message
news:uf*************@TK2MSFTNGP12.phx.gbl...
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 [out,retval] 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)
{
SAServerLib.bobClass foo = new SAServerLib.bobClass();

object o = foo.Populate();
MessageBox.Show( o.ToString() );
int[] ch = (int[])o;
MessageBox.Show( ch.ToString() );
}
I receive an exception on:
int[] ch = (int[])o;

With the message being:
"An unhandled exception of type 'System.InvalidCastException' occurred
in Safearrays.exe

Additional information: Specified cast is not valid."
ATL code:

// Populate a safe array with the value "321".
STDMETHODIMP Cbob::Populate(SAFEARRAY** saData)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 3;

*saData = SafeArrayCreate(VT_BSTR, 1, rgsabound);

long c = 3;
long lCount = 0L;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 2;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
c = 1;
lCount++;
SafeArrayPutElement(*saData, &lCount, static_cast<void*>(&c) );
return S_OK;
}
All of this code is from a sample application I'm just trying to prove
the concept with. (Eventually I'll be returning SAFEARRAY's of custom
structures.)

I've googled and MSDNed for some information, but Any advice would be
greatly appreciated.

Cheers.


Nov 17 '05 #6

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

Similar topics

0
by: Patrice FRITSCH | last post by:
Does anybody know how to retrieve a safearray from a Component ? In my asp code, I create an instance of the object, and I try to retrieve an array of 3 strings. Set myObject =...
0
by: Bob | last post by:
I have been trying to us an unmanaged dll for a while now with no good results. Most of the dll methods i can use and have been. I however have a problem with this one. I am supposed to ref 15...
4
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...
0
by: Andrew S. Giles | last post by:
Helo all, I have a standalone unmanaged C++ application that makes a call on another standalone COM server, which raises an event that should be handled in C#. I am trying to send: unsigned...
5
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...
10
by: Bryce Calhoun | last post by:
Hello, First of all, this is a .NET 1.1 component I'm creating. SUMMARY ----------------------- This component that I'm creating is, for all intents and purposes, a document parser (I'm...
1
by: Brendan Grant | last post by:
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...
5
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...
0
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#...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.