Click here to Skip to main content
14,423,206 members
Rate this:
Please Sign up or sign in to vote.
Hello world,

In my VB.net code I call a C++ dll, which should return a ouput structure.
I have a problem when the vb.net code read this structure !


The c++ structure is :

struct output_data
{
    SAFEARRAY *output1;
    SAFEARRAY *output2;
}


In the VB.net side i declare the structure like this :

Structure Output
    MarshalAs(UnmanagedType.SafeArray); Public ouput1() As String
    MarshalAs(UnmanagedType.SafeArray); Public ouput2() As String
End Structure


And the function which read the structure from the c++ dll is :

WebMethod()> _
   Public Function Test(ByRef ouput_data As Output) As Double
       Test = Cpp_Function(ouput_data)
   End Function


When i excute my soft the following exeption is raised :

System.AccessViolationException was unhandled by user code
HResult=-2147467261



Please I need your help !!
Posted
Updated 3-Jun-15 23:47pm
v2
Comments
Richard MacCutchan 4-Jun-15 7:05am
   
How have you initialiased your structure before calling the CPP function?
Member 10772496 4-Jun-15 8:48am
   
To initialize the array i do this :

ReDim ouput_data.ouput1(0 To 0)
ReDim ouput_data.ouput2(0 To 0)
ouput_data.ouput1(0) = 0
ouput_data.ouput2(0) = 0
Richard MacCutchan 4-Jun-15 10:08am
   
And what is the CPP code trying to do?
Member 10772496 4-Jun-15 10:22am
   
The C++ compute some data and complete the Safearray(BSTR) output1 and output2 in ouput structure.
Richard MacCutchan 4-Jun-15 10:44am
   
Very useful information.
Member 10772496 4-Jun-15 10:50am
   
The C++ just complete the ouput_data structure ...
What you wanted more ?
Richard MacCutchan 4-Jun-15 11:16am
   
Please edit your question, and provide full details of the code where the problem arises. We cannot guess what your program is doing.
Member 10772496 4-Jun-15 11:33am
   
The objectif of the vb.net code is to read the contained of the structure completed by the C++ DLL.

But When I try to read the ouput_data in the VB.net side, the System.AccessViolationException exception is raised.

I think my problem is that a don't use correctly the marshalling of the structure composed of SAFEARRAY coming from the C++ DLL.

What should i do to make this correctly ?

Richard MacCutchan 4-Jun-15 12:29pm
   
No idea, since we do not know what the C++ code does.
Member 10772496 8-Jun-15 4:22am
   
if it can help you, i post my code with more details.
Thanks you in advance for your help !


In the VB code i do something like :

Private Declare Function Cpp_Function Lib "XLSTATLINK.dll" (<marshalas(unmanagedtype.struct)> ByRef Input As Input_data, <marshalas(unmanagedtype.struct)> ByRef Ouput As Ouput_data) As Double

Structure Input_data
<marshalas(unmanagedtype.safearray)> Public input1() As string
<marshalas(unmanagedtype.safearray)> Public input2() As string
Public input3 As Boolean
Public input4 As Long
End Structure

<structlayout(layoutkind.sequential, pack:="8)">
Structure Ouput_data
<marshalas(unmanagedtype.safearray, safearraysubtype:="VarEnum.VT_BSTR)"> Public ouput1() As String
End Structure

<webmethod()> _
Public Function Test(ByRef Input As Input_data, ByRef Ouput As Ouput_data) As Double
ReDim Ouput.ouput1(0 To 0)
Ouput.ouput1(0) = 0
test = Cpp_Function(Input, Ouput)
End Function
And my C++ code is something like :

#pragma pack(push, 8)
struct DCA_input_data
{
SAFEARRAY *input1;
SAFEARRAY *input2;
VARIANT_BOOL input3;
long input4;
};

struct DCA_output_data
{
SAFEARRAY *ouput1;
SAFEARRAY *ouput2;
};
#pragma pack(pop) //back to whatever the previous packing mode was

void ArrayToSafearrayCopy(BSTR *array, SAFEARRAY *&safeArray)
{
int moLenght = 0;
do
{
moLenght++;
} while (array[moLenght] != nullptr);
// Create a safe array of BSTR
CComSafeArray<bstr> saData(moLenght);

for (int i = 0; i < moLenght; i++)
{
saData[i] = array[i];
}

safeArray = saData.Detach();
saData.Destroy();
}


Test_API double __stdcall Cpp_Function(Input_data *pInput, Output_data *pOutput)
{

BSTR *mInput1 = LoadSAFEARRAYStr(&pInput->input1); // convert the SafeArray table into a BSTR table
BSTR *mInput2 = LoadSAFEARRAYStr(&pInput->input2); // convert the SafeArray table into a BSTR table

BSTR *moInput1;
BSTR *moInput2;

...
...
...
//Some computation on mInput1 and mInput2 ... and results are store in moInput1 and moInput2
...
...
...

ArrayToSafearrayCopy(moInput1, pOutput->ouput1);
ArrayToSafearrayCopy(moInput2, pOutput->ouput2);

}
For you information, I done some tests in my side :

1) When I send only the input data, i have no problems !

2) I checked the C++ code with a VBA test code, i have no problem !
Richard MacCutchan 8-Jun-15 8:52am
   
The error is
E_POINTER Pointer that is not valid 0x80004003
meaning that you are using a pointer somewhere that is not pointing to your application's memory. You need to use your debugger to trace which one it is, and where the error occurs.
Member 10772496 4-Jun-15 7:14am
   
Yes before calling the C++ function, i have initialized the structure in vb.net code.

ReDim ouput_data.ouput1(0 To 0)
ReDim ouput_data.ouput2(0 To 0)
[no name] 4-Jun-15 7:27am
   
That is not initializing the array. That is redimensioning the array boundaries to 0.
Member 10772496 4-Jun-15 8:49am
   
Ok sorry, to initialize the array i do this :

ouput_data.ouput1(0) = 0
ouput_data.ouput2(0) = 0

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100