Need Help with COM call

G

Gabe Covert

I'm attempting to implement a 3rd party COM library in a C# application,
and have run up against the following problem in my development. I am
trying to use a particular method call of an object, but it looks like
tlbimp has imported the call in a way that I can't figure out how to get
my data in.

SDK:
VARIANT_BOOL ReadMemory(unsigned char* Data, long DataSize);

IL file:
.method public hidebysig newslot virtual instance bool
ReadMemory([in] unsigned int8& Data,
[in] int32 DataSize) runtime managed internalcall
{
.override [Class]::ReadMemory
} // end of method [Class]::ReadMemory

The Data parameter is supposed to be the contents of an image file (JPG,
etc) read into memory, and in my application is declared as byte[]. The
IL call has it as a pointer to a byte. How can I change the IL file to
the correct type so that I can send in a byte[]?

Thanks!

Gabe
 
N

Nicholas Paldino [.NET/C# MVP]

Gabe,

I'm a little confused by the original signature, since you have a
VARIANT_BOOL that is returned, but then you have an unsigned char pointer,
which is not automation compliant. If it was automation compliant, then I
would expect a safearray, and if it was not, I'd expect the return type to
be BOOL. If it was declared as a SafeArray, then the interop library
generated would have exposed a byte array.

If you can't change that, then what you will want to do is define your
interface in code, or modify the IL output by the TLBIMP tool (using ILDASM
to get the IL from the assembly, editing it, and then calling ILASM to
recompile it). When you re-define the COM interface, you will want to
expose the unsigned char as an IntPtr. This will cause the pointer to be
passed to your code.

Then, you will have to convert the array to a byte array and copy it
into managed memory. You can do this using the various static methods on
the Marshal class. If you need help with this, I can elaborate.

Hope this helps.
 
G

Gabe Covert

Unfortunately, I can't change it, as it's a third-party COM library...
I've dug into the IL, but being a fairly new C# developer, and with my
C++ skill sbeing fairly rusty, I'm perplexed as to what changes I would
need to make to the IL to get the parameter conversion done correctly.

Any help you can offer would be greatly appreciated!

Gabe
 
N

Nicholas Paldino [.NET/C# MVP]

Gabe,

Can you post the IDL that is used for the particular interface (you can
use OLE view to generate it). With that, I can give you a piece of code
used to represent the interface which you can cast to and use.
 
G

Gabe Covert

Here is what I find in OLE view:

[helpstring("Reads JPG, BMP, GIF, and TIFF file formats from memory")]
HRESULT _stdcall ReadMemory(
[in] unsigned char* Data,
[in] long DataSize,
[out, retval] VARIANT_BOOL* Success);

If I use the ildasm, I get the following:
.method public hidebysig newslot virtual
instance bool ReadMemory([in] unsigned IntPtr Data,
[in] int32 DataSize) runtime
managed internalcall
{
.override Identix.FaceIt.Media.IDibImage::ReadMemory
} // end of method DibImageClass::ReadMemory

Thanks!

Gabe
 
N

Nicholas Paldino [.NET/C# MVP]

Gabe,

You would need to define the interface in C# like this:

[Guid("get guid from OLEVIEW")]
// I'm assuming that the interface derives from IUnknown in COM, in which
case, this attribute is needed.
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISomeInterface
{
[retval:MarshalAs(UnmanagedType.VariantBool)]
bool Readmemory(IntPtr Data, int DataSize);
}

Then, when you implement it, you can use the methods on the Marshal
class to convert from the pointer (in Data) to the byte array you need.

If you don't want to marshal the data, you can use unsafe code and take
a pointer to void, and then just access the memory directly (however, you
need the specific permission for unsafe code). This might be a better
solution, since it you won't have to copy the memory from unmanaged to
managed.
 
G

Gabe Covert

Where would I declare this? In my code? I attempted to add a new class
library to my solution, and implement the following, but I get errors
when compiling saying that Guid and InterfaceType could not be found,
and I can't seem to find a namespace to add to the using section...

[Guid("7CA67280-8914-11D2-B814-00104BC60522")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDibImageInterface
{
[retval:MarshalAs(UnmanagedType.VariantBool)]
bool ReadMemory(IntPtr Data, int DataSize);
}

Did I do something wrong in the declaration, or where the declaration
goes?

Gabe
 
N

Nicholas Paldino [.NET/C# MVP]

Gabe,

Those classes are in the System.Runtime.InteropServices namespace.
 

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