c++ - How to call an ActiveX function with char * parameter in C# -
i have c++ function :
unsigned int readusermemory( unsigned char *lpbuffer, unsigned int iaddress, unsigned int nnumberofbyte );
which reads nnumberofbyte
bytes iaddress
of memory , places in lpbuffer
.
created atl object it( going used in c# ) interface :
[id(6), helpstring("method readusermemory")] hresult readusermemory(byte* lpbuffer, [in] ulong iaddress, [in] ulong nnumberofbyte, [out,retval] ulong* result);
i'm neither c# programmer nor experienced atl programmer! i'm going test function in c# code :
byte [] b = new byte[100]; axobj.readusermemory(b, 0, 100);
but apparently code wrong. how call method? in advance.
i think peter r has valid point, in using com complicated, because requires learning com c++ , c#, you've discovered. c++ interop option, requires learning third technology, called c++/cli, probably better fit com, can still problematic. both com , c++/cli quite big, complicated beasts, might better off declaring c function need in dll , using p/invoke, see e.g. http://msdn.microsoft.com/en-us/magazine/cc164123.aspx. if so, magic want can found in how can pass pointer array using p/invoke in c#?.
assuming want continue down com route, had play around it, , me looks need going work via type library embedded in com dll. in short, couldn't make com interop work unsigned char *lpbuffer
, although perhaps else can! type-library friendly type use safearray, way vb likes see arrays.
in case, idl becomes
[id(1)] hresult readusermemory([out] safearray(byte)* buffer, [in] ulong iaddress, [in] ulong nnumberofbyte, [out,retval] ulong* result);
your c++ implementation looks this
stdmethodimp cobj::readusermemory(safearray ** pbuffer, ulong iaddress, ulong nnumberofbyte, ulong* result) { if (pbuffer== nullptr) return e_pointer; safearray*& psa = *pbuffer; safearraybound rgsabound[1]; rgsabound[0].llbound = 0; rgsabound[0].celements = nnumberofbyte; psa = safearraycreate(vt_ui1, 1, rgsabound); if(psa == null) return e_outofmemory; void* data = nullptr; safearrayaccessdata(psa, &data); for(int i=0; i<nnumberofbyte; ++i) { ((char*)data)[i] = (char)i; } safearrayunaccessdata(psa); return s_ok; }
the safearrayunaccessdata
should called if code after safearrayaccessdata
fails.
the c# client looks this, notably have changed byte[]
system.array
static void main(string[] args) { rumlib.iobj axobj = new rumlib.obj(); array = null; axobj.readusermemory(out a, 2, 6); (int = 0; < a.length; ++i) { console.write("{0},", a.getvalue(i)); } console.writeline(); }
and output of program is
0,1,2,3,4,5,
note there v marshalling, i.e. copying of data, data comes safearray c# array. might prohibitively costly you, in case suggest go c++/cli or p/invoke.
Comments
Post a Comment