ActiveX c# Array

M

mitch

Is this really as hard as it seems. I've been truly suprised by the
lack of any information/suggestions about this. It should be so simple.

In c# I have:

double [] data = {1.0,2.0,3.0,4.0};

I need to pas this array to an ActiveX control which I have written in
Visual Studio 6 using the ActiveX wizard.

So I have full control over both sets of source code. How can I Add a
method to the ActiveX control which I can call from the c# code to pass
the array.

I've done this countless times with MFC c++ using SAFEARRYs and
SAEFARRAYs in a VARIANT. But I cannot get this to work from c#. Has
anyone ever done it?

Any help greatly appreciated,
Mitch.
 
W

Willy Denoyette [MVP]

| Is this really as hard as it seems. I've been truly suprised by the
| lack of any information/suggestions about this. It should be so simple.
|
| In c# I have:
|
| double [] data = {1.0,2.0,3.0,4.0};
|
| I need to pas this array to an ActiveX control which I have written in
| Visual Studio 6 using the ActiveX wizard.
|
| So I have full control over both sets of source code. How can I Add a
| method to the ActiveX control which I can call from the c# code to pass
| the array.
|
| I've done this countless times with MFC c++ using SAFEARRYs and
| SAEFARRAYs in a VARIANT. But I cannot get this to work from c#. Has
| anyone ever done it?
|
| Any help greatly appreciated,
| Mitch.
|

Declare your method taking a SAFEARRAY of double in IDL.

HRESULT PassDoubleArray([in] SAFEARRAY(double) arr);

implement like:

STDMETHODIMP CTest::passDoubleArray(SAFEARRAY * arr)
{
double* temp;
SafeArrayAccessData(arr, (void**)&temp);
long ubound;
SafeArrayGetUBound(arr, 1, &ubound);
for(int i = 0; i <= ubound; i++)
// use array data
..
SafeArrayUnaccessData(arr);
return S_OK;
}




and call it from C# like this:

double[] darr = new double[5] {1.1, 2.2, 3.3, 4.44, 5.2356};

obj.PassDoubleArray(darr);

Willy.
 
M

mitch

Hi, thanks for your reply. It doesn't work :(

In my ODL file I have:

[id(3)] void UseArray([in]SAFEARRAY(double) pArray);

In my ctl header I have:

afx_msg void UseArray(SAFEARRAY* pArray);

And in my ctl cpp file I have:

void CTestOCXCtrl::UseArray(SAFEARRAY* pArray)
{
AfxMessageBox("Use Array");
}

Finally in my DISPATCH_MAP of my ctl cpp I have:

DISP_FUNCTION(CTestOCXCtrl, "UseArray", UseArray, VT_EMPTY, VTS_R8)

I get a type mismatch error when running from c# using exactly the c#
call you suggested.

Is my DISPATCH_MAP declaration in error?
 
W

Willy Denoyette [MVP]

| Hi, thanks for your reply. It doesn't work :(
|
| In my ODL file I have:
|
| [id(3)] void UseArray([in]SAFEARRAY(double) pArray);
|
| In my ctl header I have:
|
| afx_msg void UseArray(SAFEARRAY* pArray);
|
| And in my ctl cpp file I have:
| |
void CTestOCXCtrl::UseArray(SAFEARRAY* pArray)
| {
| AfxMessageBox("Use Array");
| }
|
| Finally in my DISPATCH_MAP of my ctl cpp I have:
|
| DISP_FUNCTION(CTestOCXCtrl, "UseArray", UseArray, VT_EMPTY, VTS_R8)
|
| I get a type mismatch error when running from c# using exactly the c#
| call you suggested.
|
| Is my DISPATCH_MAP declaration in error?
|

Oh, MFC and Dispatch interfaces, don't know anything about SAFEARRAY's, try
to pass the argument as VARIANT array of doubles, or a VARIANT array of
VARIANTs.

ODL..
([in] VARIANT arr)

afx_msg void UseArray(VARIANT var);


Implemenattion ...
void CTestOCXCtrl::UseArray(VARIANT var)
{
HRESULT hr = S_OK;
long low, up, dim;
VARTYPE vt = V_VT(&arr);
if (vt & VT_ARRAY) {
LPSAFEARRAY psa = V_ARRAY(&arr);
dim = SafeArrayGetDim(psa);
SafeArrayGetLBound(psa, dim, &low);
SafeArrayGetUBound(psa, dim, &up);
switch(vt)
{
case (VT_ARRAY | VT_R8): // array of doubles
{
double* temp;
SafeArrayAccessData(psa, (void**)&temp);
for (int i = low; i <= up; i++)
{
// use array data
}
SafeArrayUnaccessData(psa);
break;
}
default:
hr = E_INVALIDARG;
}
}
else
hr = E_INVALIDARG;
return hr;
}

Usage:
xxx.UseArray((object)arrayOfDoubles); // need to cast to object (VARIANT ==
object)

Willy.
 
M

mitch

Sadly this dies not work either. I've pretty much exhausted every
possibility. Very sad state of affairs. I have:

In ODL file:

[id(3)] void UseArray([in] VARIANT arr);

In ctl header:

afx_msg void UseArray(VARIANT var);

In ctl cpp:

void CTestOCXCtrl::UseArray(VARIANT pArray)
{
AfxMessageBox("Use Array");
}

And from c# I have:

double[] darr = new double[5] {1.1, 2.2, 3.3, 4.44, 5.2356};

axTestOCX1.UseArray((object)darr);

Bizzarely, when I execute the above c# command I see the "Use Array"
text box come up TWICE! After which I get an exeption "Object Reference
Not Set To An Instance Of Object"

:(

This shouldn't be at all hard.
 
W

Willy Denoyette [MVP]

| Sadly this dies not work either. I've pretty much exhausted every
| possibility. Very sad state of affairs. I have:
|
| In ODL file:
|
| [id(3)] void UseArray([in] VARIANT arr);
|
| In ctl header:
|
| afx_msg void UseArray(VARIANT var);
|
| In ctl cpp:
|
| void CTestOCXCtrl::UseArray(VARIANT pArray)
| {
| AfxMessageBox("Use Array");
| }
|
| And from c# I have:
|
| double[] darr = new double[5] {1.1, 2.2, 3.3, 4.44, 5.2356};
|
| axTestOCX1.UseArray((object)darr);
|
| Bizzarely, when I execute the above c# command I see the "Use Array"
| text box come up TWICE! After which I get an exeption "Object Reference
| Not Set To An Instance Of Object"
|
| :(
|
| This shouldn't be at all hard.
|
It's not possible to get the dialog twice without calling the method twice.
Don't know why you get the null ref. exception, without you posting the
whole code.
Why not run this in the debugger and see what happens.

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