W
Wizfrog
Hello and thanks for reading...
I am using a C++ unmanaged ActiveX (ocx) that allows me to read a
specific file format, and get data out of those.
I use C# .Net.
To use the ActiveX, I simply added it to my toolbox, and create an
instance in a form. Until there, all is good. I can read files, get
the data etc... even if I need to 'copy' the data from the unmanaged
side to the managed side.
Now where I hit a rodblock is when I try to copy the data back to the
ActiveX:
I need to pass a float[] to the COM object to then 'save' the data in
the original (proprietary) file format.
The ActiveX function in C++ is defined as
PutValue(int dataID, float* parray, uint size)
however in C#, the converted function by the ActiveX importer becomes
PutValue(int dataID, ref float parray, int size)
All the research I've done to figure out a solution leads me to
conclude that I need to Marshal the float* parameter into "IntPtr"
That's where I am stuck:
The imported library is already in managed C#, and shows as non-
editable 'MetaData', and it doesn't seem like I can override an
Interface declaration. So I don't see a way to Marshal the parameter.
So I tried to use COM interop directly, by calling the ActiveX.ocx
using [DllImport]
[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#3")]
[return] int ID public static extern int Load(string
filename);
[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#60")]
public static extern int PutValueEx(int ID, IntPtr pt, int
size);
I first had to figure out the entry point # in order to access the
functions, but got so far.
Now, calling the ocx directly, I get "Attempted to read or write
protected memory" error when trying to load the file.
Obviously there is something else that's being done when importing an
ActiveX through the toolbox.
I also tried to import the library directly, using AXIMP.EXE
It created 2 DLLs. One seems to be the managed interop library I can
get the code from if I use the "/source" tag, the other is the actual
COM DLL.
Problem, if I reference the 1st DLL, or import the source in my
project, I see that it calls the second DLL that includes the actual
functions.
So I tried to use [DllImport] directly on that second DLL, but there
it is not able to find an entry point.
Using LibDump, I could see the type library information from the ocx
file, but I can't see anything one either of the 2 DLLs generated,
which leads me to think they are missing the interface definition.
So, I'm trying to figure out a way out of this mess:
Either by finding a way to override the interface in the imported
ActiveX control from the toolbox, and marshal the paramter properly
Or
By finding the way to generate the DLL properly so I can import it
directly with [DllImport]
Or
figure out what is wrong when calling the .ocx file directly with
[DllImport]
Any suggestion would be greatly appreciated.
Note:
1) I do not need any of the 'control' form features, only to load the
file, read the data, put data back in and save it.
2) I did ask the vendor for the file format, so I could read/write it
directly in C#, but I didn't get anywhere. Would have been my
preference but this is not an option.
I am using a C++ unmanaged ActiveX (ocx) that allows me to read a
specific file format, and get data out of those.
I use C# .Net.
To use the ActiveX, I simply added it to my toolbox, and create an
instance in a form. Until there, all is good. I can read files, get
the data etc... even if I need to 'copy' the data from the unmanaged
side to the managed side.
Now where I hit a rodblock is when I try to copy the data back to the
ActiveX:
I need to pass a float[] to the COM object to then 'save' the data in
the original (proprietary) file format.
The ActiveX function in C++ is defined as
PutValue(int dataID, float* parray, uint size)
however in C#, the converted function by the ActiveX importer becomes
PutValue(int dataID, ref float parray, int size)
All the research I've done to figure out a solution leads me to
conclude that I need to Marshal the float* parameter into "IntPtr"
That's where I am stuck:
The imported library is already in managed C#, and shows as non-
editable 'MetaData', and it doesn't seem like I can override an
Interface declaration. So I don't see a way to Marshal the parameter.
So I tried to use COM interop directly, by calling the ActiveX.ocx
using [DllImport]
[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#3")]
[return] int ID public static extern int Load(string
filename);
[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#60")]
public static extern int PutValueEx(int ID, IntPtr pt, int
size);
I first had to figure out the entry point # in order to access the
functions, but got so far.
Now, calling the ocx directly, I get "Attempted to read or write
protected memory" error when trying to load the file.
Obviously there is something else that's being done when importing an
ActiveX through the toolbox.
I also tried to import the library directly, using AXIMP.EXE
It created 2 DLLs. One seems to be the managed interop library I can
get the code from if I use the "/source" tag, the other is the actual
COM DLL.
Problem, if I reference the 1st DLL, or import the source in my
project, I see that it calls the second DLL that includes the actual
functions.
So I tried to use [DllImport] directly on that second DLL, but there
it is not able to find an entry point.
Using LibDump, I could see the type library information from the ocx
file, but I can't see anything one either of the 2 DLLs generated,
which leads me to think they are missing the interface definition.
So, I'm trying to figure out a way out of this mess:
Either by finding a way to override the interface in the imported
ActiveX control from the toolbox, and marshal the paramter properly
Or
By finding the way to generate the DLL properly so I can import it
directly with [DllImport]
Or
figure out what is wrong when calling the .ocx file directly with
[DllImport]
Any suggestion would be greatly appreciated.
Note:
1) I do not need any of the 'control' form features, only to load the
file, read the data, put data back in and save it.
2) I did ask the vendor for the file format, so I could read/write it
directly in C#, but I didn't get anywhere. Would have been my
preference but this is not an option.