473,725 Members | 2,032 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

PInvoke Marshalling....

Greetings!

I'm trying to call this method in a c# app...

SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandle, unsigned char *pData, long max_length);

So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilder pData, long max_length);

Keep getting a PInvokeStackImb alance error and I think it's the 2nd paramter
pData because I've referenced the device handler and the long typedef is
pretty obvious.

For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string

HELP!
Thanks.
Dan.
Oct 23 '07 #1
11 2700
Daniel,

Actually, it's not pretty obvious. In C++, long corresponds to a 32-bit
integer, which in C#, is an int. Also, you should declare how your strings
are marshaled in the DllImport attribute. All-in-all, your declaration
should look like this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilder pData, int max_length);

Also, if the pData parameter is not going to be written to by the API
function, you can pass it as a string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8******** ******@TK2MSFTN GP03.phx.gbl...
Greetings!

I'm trying to call this method in a c# app...

SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandle, unsigned char *pData, long max_length);

So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilder pData, long max_length);

Keep getting a PInvokeStackImb alance error and I think it's the 2nd
paramter pData because I've referenced the device handler and the long
typedef is pretty obvious.

For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string

HELP!
Thanks.
Dan.

Oct 23 '07 #2
Nicholas,

Excellent, thanks for the prompt reply!

pData is a buffer that I create, then pass into the function to populate.
Does the parameter as a StringBuilder marshall this data correctly?

Thanks.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote in
message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
Daniel,

Actually, it's not pretty obvious. In C++, long corresponds to a
32-bit integer, which in C#, is an int. Also, you should declare how your
strings are marshaled in the DllImport attribute. All-in-all, your
declaration should look like this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilder pData, int max_length);

Also, if the pData parameter is not going to be written to by the API
function, you can pass it as a string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8******** ******@TK2MSFTN GP03.phx.gbl...
>Greetings!

I'm trying to call this method in a c# app...

SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandle , unsigned char *pData, long max_length);

So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilde r pData, long max_length);

Keep getting a PInvokeStackImb alance error and I think it's the 2nd
paramter pData because I've referenced the device handler and the long
typedef is pretty obvious.

For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string

HELP!
Thanks.
Dan.


Oct 23 '07 #3
Daniel,

Yes, if the API function is going to write to the buffer, then passing a
StringBuilder will cause the data to be marshaled back to you correctly.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
Nicholas,

Excellent, thanks for the prompt reply!

pData is a buffer that I create, then pass into the function to populate.
Does the parameter as a StringBuilder marshall this data correctly?

Thanks.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
>Daniel,

Actually, it's not pretty obvious. In C++, long corresponds to a
32-bit integer, which in C#, is an int. Also, you should declare how
your strings are marshaled in the DllImport attribute. All-in-all, your
declaration should look like this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilde r pData, int max_length);

Also, if the pData parameter is not going to be written to by the API
function, you can pass it as a string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8******* *******@TK2MSFT NGP03.phx.gbl.. .
>>Greetings!

I'm trying to call this method in a c# app...

SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandl e, unsigned char *pData, long max_length);

So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuild er pData, long max_length);

Keep getting a PInvokeStackImb alance error and I think it's the 2nd
paramter pData because I've referenced the device handler and the long
typedef is pretty obvious.

For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string

HELP!
Thanks.
Dan.



Oct 23 '07 #4
Nicholas,

I've just been reading through the API guide, and realised that it won't
pass me back the data in a synchronous manner.

To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The host
applicaition provides a message handler for the ack from the connected
device."

Eeek! In .Net, is there a way to listen for messages? I've worked a little
with message maps, but that was way back and have not see this sort of basic
message handling in .net before...

Cheers.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote in
message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
Daniel,

Yes, if the API function is going to write to the buffer, then passing
a StringBuilder will cause the data to be marshaled back to you correctly.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
>Nicholas,

Excellent, thanks for the prompt reply!

pData is a buffer that I create, then pass into the function to populate.
Does the parameter as a StringBuilder marshall this data correctly?

Thanks.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
>>Daniel,

Actually, it's not pretty obvious. In C++, long corresponds to a
32-bit integer, which in C#, is an int. Also, you should declare how
your strings are marshaled in the DllImport attribute. All-in-all, your
declaration should look like this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuild er pData, int max_length);

Also, if the pData parameter is not going to be written to by the API
function, you can pass it as a string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8****** ********@TK2MSF TNGP03.phx.gbl. ..
Greetings!

I'm trying to call this method in a c# app...

SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandle , unsigned char *pData, long max_length);

So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilde r pData, long max_length);

Keep getting a PInvokeStackImb alance error and I think it's the 2nd
paramter pData because I've referenced the device handler and the long
typedef is pretty obvious.

For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string

HELP!
Thanks.
Dan.



Oct 23 '07 #5
Daniel,

Yes, there is. You can create a class which implements the
IMessageFilter interface and then call the AddMessageFilte r method on the
Application class, passing your implementation. Then, in the
PreFilterMessag e method, you would check for your message.

There might be a more subtle issue here. When the function returns, is
the string already written to? Or is the string written to when the message
is sent to the application? If it is the former, then the code you have is
ok. If it is the latter, you will have to change your declaration of the
unsigned char * parameter to an IntPtr, and allocate the memory that you
need yourself.

Then, in the handler for the message, you will have to manually marshal
the string to managed code using the static methods on the Marshal class
(freeing the memory of course as well).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u%******** ********@TK2MSF TNGP03.phx.gbl. ..
Nicholas,

I've just been reading through the API guide, and realised that it won't
pass me back the data in a synchronous manner.

To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The host
applicaition provides a message handler for the ack from the connected
device."

Eeek! In .Net, is there a way to listen for messages? I've worked a little
with message maps, but that was way back and have not see this sort of
basic message handling in .net before...

Cheers.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
>Daniel,

Yes, if the API function is going to write to the buffer, then passing
a StringBuilder will cause the data to be marshaled back to you
correctly.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2******* *********@TK2MS FTNGP05.phx.gbl ...
>>Nicholas,

Excellent, thanks for the prompt reply!

pData is a buffer that I create, then pass into the function to
populate. Does the parameter as a StringBuilder marshall this data
correctly?

Thanks.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
Daniel,

Actually, it's not pretty obvious. In C++, long corresponds to a
32-bit integer, which in C#, is an int. Also, you should declare how
your strings are marshaled in the DllImport attribute. All-in-all,
your declaration should look like this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuilde r pData, int max_length);

Also, if the pData parameter is not going to be written to by the
API function, you can pass it as a string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8***** *********@TK2MS FTNGP03.phx.gbl ...
Greetings !
>
I'm trying to call this method in a c# app...
>
SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
DeviceHandl e, unsigned char *pData, long max_length);
>
So far I've got this:
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_SetVersio nBuffer(IntPtr
DeviceHandl e, StringBuilder pData, long max_length);
>
Keep getting a PInvokeStackImb alance error and I think it's the 2nd
paramter pData because I've referenced the device handler and the long
typedef is pretty obvious.
>
For the 2nd paramter I've tried the following without success:
byte[]
char[]
string
StringBuilder
[MarshalAs(Unman agedType.AnsiBS tr)] string
>
HELP!
Thanks.
Dan.
>




Oct 23 '07 #6

I pass in a handle of the windows into the API as part of an initialisation
call. Could I then just override "WndProc"?

It's doing the latter, and only sending a message when the parameter has
been sent to the buffer. When you say "allocate the memory" yourself, I'm
not sure what you mean. I'll provide the IntPtr parameter, and according the
API manual, I'll have a global buffer space that I register with the API
which should be populated with the event call... Does that sound feasible?

Thanks for your help and guidance!

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote in
message news:Oo******** ******@TK2MSFTN GP04.phx.gbl...
Daniel,

Yes, there is. You can create a class which implements the
IMessageFilter interface and then call the AddMessageFilte r method on the
Application class, passing your implementation. Then, in the
PreFilterMessag e method, you would check for your message.

There might be a more subtle issue here. When the function returns, is
the string already written to? Or is the string written to when the
message is sent to the application? If it is the former, then the code
you have is ok. If it is the latter, you will have to change your
declaration of the unsigned char * parameter to an IntPtr, and allocate
the memory that you need yourself.

Then, in the handler for the message, you will have to manually marshal
the string to managed code using the static methods on the Marshal class
(freeing the memory of course as well).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u%******** ********@TK2MSF TNGP03.phx.gbl. ..
>Nicholas,

I've just been reading through the API guide, and realised that it won't
pass me back the data in a synchronous manner.

To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The host
applicaition provides a message handler for the ack from the connected
device."

Eeek! In .Net, is there a way to listen for messages? I've worked a
little with message maps, but that was way back and have not see this
sort of basic message handling in .net before...

Cheers.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
>>Daniel,

Yes, if the API function is going to write to the buffer, then
passing a StringBuilder will cause the data to be marshaled back to you
correctly.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2****** **********@TK2M SFTNGP05.phx.gb l...
Nicholas,

Excellent, thanks for the prompt reply!

pData is a buffer that I create, then pass into the function to
populate. Does the parameter as a StringBuilder marshall this data
correctly?

Thanks.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
wrote in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
Daniel,
>
Actually, it's not pretty obvious. In C++, long corresponds to a
32-bit integer, which in C#, is an int. Also, you should declare how
your strings are marshaled in the DllImport attribute. All-in-all,
your declaration should look like this:
>
[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
StringBuild er pData, int max_length);
>
Also, if the pData parameter is not going to be written to by the
API function, you can pass it as a string.
>
>
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
>
>
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u8**** **********@TK2M SFTNGP03.phx.gb l...
>Greeting s!
>>
>I'm trying to call this method in a c# app...
>>
> SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
>DeviceHand le, unsigned char *pData, long max_length);
>>
>So far I've got this:
> [DllImport("Depe ndencies\\SNAPI .DLL")]
> public static extern int SNAPI_SetVersio nBuffer(IntPtr
>DeviceHand le, StringBuilder pData, long max_length);
>>
>Keep getting a PInvokeStackImb alance error and I think it's the 2nd
>paramter pData because I've referenced the device handler and the
>long typedef is pretty obvious.
>>
>For the 2nd paramter I've tried the following without success:
> byte[]
> char[]
> string
> StringBuilder
> [MarshalAs(Unman agedType.AnsiBS tr)] string
>>
>HELP!
>Thanks.
>Dan.
>>
>
>




Oct 23 '07 #7
Daniel,

I was thinking this is a little odd, since the parameter is named
"DeviceHand le" and not indicative that it is a windows handle. If it is
indeed a windows handle you are passing to the method, then you can override
the WndProc method of the control that contains that windows handle to look
for the message sent to you.

You will have to change your API declaration to this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle, IntPtr
pData, int max_length);

And then call it like this:

// dataBuffer need to be accessible by the override of WndProc as well.
dataBuffer = Marshal.AllocHG lobal(dataBuffe rLength);

// Make the API call:
SNAPI_SetVersio nBuffer(windowH andle, dataBuffer, dataBufferLengt h);

Then, in your override of WndProc, in the section that handles the
message to the window:

// Get the string.
string data = Marshal.PtrToSt ringAnsi(dataBu ffer);

// Free the memory.
Marshal.FreeHGl obal(dataBuffer );

// Work with the string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:O3******** ********@TK2MSF TNGP06.phx.gbl. ..
>
I pass in a handle of the windows into the API as part of an
initialisation call. Could I then just override "WndProc"?

It's doing the latter, and only sending a message when the parameter has
been sent to the buffer. When you say "allocate the memory" yourself, I'm
not sure what you mean. I'll provide the IntPtr parameter, and according
the API manual, I'll have a global buffer space that I register with the
API which should be populated with the event call... Does that sound
feasible?

Thanks for your help and guidance!

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:Oo******** ******@TK2MSFTN GP04.phx.gbl...
>Daniel,

Yes, there is. You can create a class which implements the
IMessageFilt er interface and then call the AddMessageFilte r method on the
Application class, passing your implementation. Then, in the
PreFilterMessa ge method, you would check for your message.

There might be a more subtle issue here. When the function returns,
is the string already written to? Or is the string written to when the
message is sent to the application? If it is the former, then the code
you have is ok. If it is the latter, you will have to change your
declaration of the unsigned char * parameter to an IntPtr, and allocate
the memory that you need yourself.

Then, in the handler for the message, you will have to manually
marshal the string to managed code using the static methods on the
Marshal class (freeing the memory of course as well).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u%******* *********@TK2MS FTNGP03.phx.gbl ...
>>Nicholas,

I've just been reading through the API guide, and realised that it won't
pass me back the data in a synchronous manner.

To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The
host applicaition provides a message handler for the ack from the
connected device."

Eeek! In .Net, is there a way to listen for messages? I've worked a
little with message maps, but that was way back and have not see this
sort of basic message handling in .net before...

Cheers.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
Daniel,

Yes, if the API function is going to write to the buffer, then
passing a StringBuilder will cause the data to be marshaled back to you
correctly.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2***** ***********@TK2 MSFTNGP05.phx.g bl...
Nicholas,
>
Excellent , thanks for the prompt reply!
>
pData is a buffer that I create, then pass into the function to
populate. Does the parameter as a StringBuilder marshall this data
correctly ?
>
Thanks.
Dan.
>
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
wrote in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
>Daniel,
>>
> Actually, it's not pretty obvious. In C++, long corresponds to a
>32-bit integer, which in C#, is an int. Also, you should declare how
>your strings are marshaled in the DllImport attribute. All-in-all,
>your declaration should look like this:
>>
>[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
>public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
>StringBuil der pData, int max_length);
>>
> Also, if the pData parameter is not going to be written to by the
>API function, you can pass it as a string.
>>
>>
>--
> - Nicholas Paldino [.NET/C# MVP]
> - mv*@spam.guard. caspershouse.co m
>>
>>
>"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in
>message news:u8******** ******@TK2MSFTN GP03.phx.gbl...
>>Greetings !
>>>
>>I'm trying to call this method in a c# app...
>>>
>> SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
>>DeviceHan dle, unsigned char *pData, long max_length);
>>>
>>So far I've got this:
>> [DllImport("Depe ndencies\\SNAPI .DLL")]
>> public static extern int SNAPI_SetVersio nBuffer(IntPtr
>>DeviceHan dle, StringBuilder pData, long max_length);
>>>
>>Keep getting a PInvokeStackImb alance error and I think it's the 2nd
>>paramte r pData because I've referenced the device handler and the
>>long typedef is pretty obvious.
>>>
>>For the 2nd paramter I've tried the following without success:
>> byte[]
>> char[]
>> string
>> StringBuilder
>> [MarshalAs(Unman agedType.AnsiBS tr)] string
>>>
>>HELP!
>>Thanks.
>>Dan.
>>>
>>
>>
>
>




Oct 23 '07 #8
Well, kind of...

A little context may help. I'm writing a front end into a driver for a USB
connected imaging scanner.

DeviceHandle is the handle that I keep hold of for the currently connected
device.

The first call I make into the API though, is
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_Init(IntP tr hwend, IntPtr[]
DeviceHandles, ref int NumDevices);
This basically expects a windows handler, along with a buffer array which it
uses to populate with scanners that are currently attached to the system.

I've overriden WndProc, and it's correctly getting the message I'd expect,
in this case it's the WM_VERSION message. All I'm trying to do is initially
query the scanner for the firmware version as a simple way of exchanging
data before I get onto imaging and video!

OnConnect type event does this:
int status = 0;
status = DriverProxy.SNA PI_SetVersionBu ffer(handle,
_versionBuffer, _versionBuffer. Length);
status = DriverProxy.SNA PI_TransmitVers ion(handle);
_versionBuffer is global StringBuilder, and transmit version tells the scan
to please send me the firmware version to the allocated buffer.

In WndProc override:
protected override void WndProc(ref Message m)
{
switch ((uint)m.Msg)
{
case DriverProxy.WM_ SWVERSION:
// should now have a _versionbuffer full of grand stuff
FirmwareVersion Label.Text = _versionBuffer. ToString();
break;

}
Debug.WriteLine If(m.Msg 0x8000 && m.Msg < 0xBFFF, "HIT! " +
m.Msg.ToString( ));
base.WndProc(re f m);
}

Now I've a label that gets the Firmware version text assigned to it, but
this is currently blank, and can confirm that the WM_SWVERSION message comes
through...

Hope that helps to explain what I'm trying to achieve.
Thanks again.
Dan.
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote in
message news:Oa******** ******@TK2MSFTN GP03.phx.gbl...
Daniel,

I was thinking this is a little odd, since the parameter is named
"DeviceHand le" and not indicative that it is a windows handle. If it is
indeed a windows handle you are passing to the method, then you can
override the WndProc method of the control that contains that windows
handle to look for the message sent to you.

You will have to change your API declaration to this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
IntPtr pData, int max_length);

And then call it like this:

// dataBuffer need to be accessible by the override of WndProc as well.
dataBuffer = Marshal.AllocHG lobal(dataBuffe rLength);

// Make the API call:
SNAPI_SetVersio nBuffer(windowH andle, dataBuffer, dataBufferLengt h);

Then, in your override of WndProc, in the section that handles the
message to the window:

// Get the string.
string data = Marshal.PtrToSt ringAnsi(dataBu ffer);

// Free the memory.
Marshal.FreeHGl obal(dataBuffer );

// Work with the string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:O3******** ********@TK2MSF TNGP06.phx.gbl. ..
>>
I pass in a handle of the windows into the API as part of an
initialisati on call. Could I then just override "WndProc"?

It's doing the latter, and only sending a message when the parameter has
been sent to the buffer. When you say "allocate the memory" yourself, I'm
not sure what you mean. I'll provide the IntPtr parameter, and according
the API manual, I'll have a global buffer space that I register with the
API which should be populated with the event call... Does that sound
feasible?

Thanks for your help and guidance!

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:Oo******** ******@TK2MSFTN GP04.phx.gbl...
>>Daniel,

Yes, there is. You can create a class which implements the
IMessageFilte r interface and then call the AddMessageFilte r method on
the Application class, passing your implementation. Then, in the
PreFilterMess age method, you would check for your message.

There might be a more subtle issue here. When the function returns,
is the string already written to? Or is the string written to when the
message is sent to the application? If it is the former, then the code
you have is ok. If it is the latter, you will have to change your
declaration of the unsigned char * parameter to an IntPtr, and allocate
the memory that you need yourself.

Then, in the handler for the message, you will have to manually
marshal the string to managed code using the static methods on the
Marshal class (freeing the memory of course as well).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u%****** **********@TK2M SFTNGP03.phx.gb l...
Nicholas,

I've just been reading through the API guide, and realised that it
won't pass me back the data in a synchronous manner.

To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The
host applicaition provides a message handler for the ack from the
connected device."

Eeek! In .Net, is there a way to listen for messages? I've worked a
little with message maps, but that was way back and have not see this
sort of basic message handling in .net before...

Cheers.
Dan.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
wrote in message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
Daniel,
>
Yes, if the API function is going to write to the buffer, then
passing a StringBuilder will cause the data to be marshaled back to
you correctly.
>
>
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
>
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:%2**** ************@TK 2MSFTNGP05.phx. gbl...
>Nicholas ,
>>
>Excellen t, thanks for the prompt reply!
>>
>pData is a buffer that I create, then pass into the function to
>populate . Does the parameter as a StringBuilder marshall this data
>correctl y?
>>
>Thanks.
>Dan.
>>
>"Nichola s Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
>wrote in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
>>Daniel,
>>>
>> Actually, it's not pretty obvious. In C++, long corresponds to a
>>32-bit integer, which in C#, is an int. Also, you should declare
>>how your strings are marshaled in the DllImport attribute.
>>All-in-all, your declaration should look like this:
>>>
>>[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
>>public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
>>StringBui lder pData, int max_length);
>>>
>> Also, if the pData parameter is not going to be written to by the
>>API function, you can pass it as a string.
>>>
>>>
>>--
>> - Nicholas Paldino [.NET/C# MVP]
>> - mv*@spam.guard. caspershouse.co m
>>>
>>>
>>"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in
>>message news:u8******** ******@TK2MSFTN GP03.phx.gbl...
>>>Greeting s!
>>>>
>>>I'm trying to call this method in a c# app...
>>>>
>>> SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
>>>DeviceHa ndle, unsigned char *pData, long max_length);
>>>>
>>>So far I've got this:
>>> [DllImport("Depe ndencies\\SNAPI .DLL")]
>>> public static extern int SNAPI_SetVersio nBuffer(IntPtr
>>>DeviceHa ndle, StringBuilder pData, long max_length);
>>>>
>>>Keep getting a PInvokeStackImb alance error and I think it's the 2nd
>>>paramt er pData because I've referenced the device handler and the
>>>long typedef is pretty obvious.
>>>>
>>>For the 2nd paramter I've tried the following without success:
>>> byte[]
>>> char[]
>>> string
>>> StringBuilder
>>> [MarshalAs(Unman agedType.AnsiBS tr)] string
>>>>
>>>HELP!
>>>Thanks .
>>>Dan.
>>>>
>>>
>>>
>>
>>
>
>




Oct 23 '07 #9
Daniel,

My previous post outlines what you have to do with allocating the
buffer.

When you pass a StringBuilder, the P/Invoke layer creates a buffer of
unmanaged memory, and passes the pointer to that, populated with the
contents of the string builder. Upon return, the P/Invoke layer marshals
the information from that unmanaged buffer back into the StringBuilder, and
disposes of the pointer.

However, this API is holding onto the pointer, so you have to do the
same.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:O7******** ******@TK2MSFTN GP02.phx.gbl...
Well, kind of...

A little context may help. I'm writing a front end into a driver for a USB
connected imaging scanner.

DeviceHandle is the handle that I keep hold of for the currently connected
device.

The first call I make into the API though, is
[DllImport("Depe ndencies\\SNAPI .DLL")]
public static extern int SNAPI_Init(IntP tr hwend, IntPtr[]
DeviceHandles, ref int NumDevices);
This basically expects a windows handler, along with a buffer array which
it uses to populate with scanners that are currently attached to the
system.

I've overriden WndProc, and it's correctly getting the message I'd expect,
in this case it's the WM_VERSION message. All I'm trying to do is
initially query the scanner for the firmware version as a simple way of
exchanging data before I get onto imaging and video!

OnConnect type event does this:
int status = 0;
status = DriverProxy.SNA PI_SetVersionBu ffer(handle,
_versionBuffer, _versionBuffer. Length);
status = DriverProxy.SNA PI_TransmitVers ion(handle);
_versionBuffer is global StringBuilder, and transmit version tells the
scan to please send me the firmware version to the allocated buffer.

In WndProc override:
protected override void WndProc(ref Message m)
{
switch ((uint)m.Msg)
{
case DriverProxy.WM_ SWVERSION:
// should now have a _versionbuffer full of grand stuff
FirmwareVersion Label.Text = _versionBuffer. ToString();
break;

}
Debug.WriteLine If(m.Msg 0x8000 && m.Msg < 0xBFFF, "HIT! " +
m.Msg.ToString( ));
base.WndProc(re f m);
}

Now I've a label that gets the Firmware version text assigned to it, but
this is currently blank, and can confirm that the WM_SWVERSION message
comes through...

Hope that helps to explain what I'm trying to achieve.
Thanks again.
Dan.
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:Oa******** ******@TK2MSFTN GP03.phx.gbl...
>Daniel,

I was thinking this is a little odd, since the parameter is named
"DeviceHandl e" and not indicative that it is a windows handle. If it is
indeed a windows handle you are passing to the method, then you can
override the WndProc method of the control that contains that windows
handle to look for the message sent to you.

You will have to change your API declaration to this:

[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
public static extern int SNAPI_SetVersio nBuffer(IntPtr DeviceHandle,
IntPtr pData, int max_length);

And then call it like this:

// dataBuffer need to be accessible by the override of WndProc as well.
dataBuffer = Marshal.AllocHG lobal(dataBuffe rLength);

// Make the API call:
SNAPI_SetVersi onBuffer(window Handle, dataBuffer, dataBufferLengt h);

Then, in your override of WndProc, in the section that handles the
message to the window:

// Get the string.
string data = Marshal.PtrToSt ringAnsi(dataBu ffer);

// Free the memory.
Marshal.FreeHG lobal(dataBuffe r);

// Work with the string.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:O3******* *********@TK2MS FTNGP06.phx.gbl ...
>>>
I pass in a handle of the windows into the API as part of an
initialisatio n call. Could I then just override "WndProc"?

It's doing the latter, and only sending a message when the parameter has
been sent to the buffer. When you say "allocate the memory" yourself,
I'm not sure what you mean. I'll provide the IntPtr parameter, and
according the API manual, I'll have a global buffer space that I
register with the API which should be populated with the event call...
Does that sound feasible?

Thanks for your help and guidance!

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:Oo******** ******@TK2MSFTN GP04.phx.gbl...
Daniel,

Yes, there is. You can create a class which implements the
IMessageFilt er interface and then call the AddMessageFilte r method on
the Application class, passing your implementation. Then, in the
PreFilterMes sage method, you would check for your message.

There might be a more subtle issue here. When the function returns,
is the string already written to? Or is the string written to when the
message is sent to the application? If it is the former, then the code
you have is ok. If it is the latter, you will have to change your
declaratio n of the unsigned char * parameter to an IntPtr, and allocate
the memory that you need yourself.

Then, in the handler for the message, you will have to manually
marshal the string to managed code using the static methods on the
Marshal class (freeing the memory of course as well).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in message
news:u%***** ***********@TK2 MSFTNGP03.phx.g bl...
Nicholas,
>
I've just been reading through the API guide, and realised that it
won't pass me back the data in a synchronous manner.
>
To quote:
"A command function returns immediately to the host application...
After the command is processed, by the scanner, the host application
received a Windows message indicating the command was processed. The
host applicaition provides a message handler for the ack from the
connected device."
>
Eeek! In .Net, is there a way to listen for messages? I've worked a
little with message maps, but that was way back and have not see this
sort of basic message handling in .net before...
>
Cheers.
Dan.
>
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
wrote in message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
>Daniel,
>>
> Yes, if the API function is going to write to the buffer, then
>passing a StringBuilder will cause the data to be marshaled back to
>you correctly.
>>
>>
>--
> - Nicholas Paldino [.NET/C# MVP]
> - mv*@spam.guard. caspershouse.co m
>>
>"Daniel Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in
>message news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
>>Nichola s,
>>>
>>Excellent , thanks for the prompt reply!
>>>
>>pData is a buffer that I create, then pass into the function to
>>populat e. Does the parameter as a StringBuilder marshall this data
>>correctly ?
>>>
>>Thanks.
>>Dan.
>>>
>>"Nichol as Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
>>wrote in message news:ec******** *****@TK2MSFTNG P03.phx.gbl...
>>>Daniel ,
>>>>
>>> Actually, it's not pretty obvious. In C++, long corresponds to
>>>a 32-bit integer, which in C#, is an int. Also, you should declare
>>>how your strings are marshaled in the DllImport attribute.
>>>All-in-all, your declaration should look like this:
>>>>
>>>[DllImport("Depe ndencies\\SNAPI .DLL", CharSet=CharSet .Ansi)]
>>>public static extern int SNAPI_SetVersio nBuffer(IntPtr
>>>DeviceHa ndle, StringBuilder pData, int max_length);
>>>>
>>> Also, if the pData parameter is not going to be written to by
>>>the API function, you can pass it as a string.
>>>>
>>>>
>>>--
>>> - Nicholas Paldino [.NET/C# MVP]
>>> - mv*@spam.guard. caspershouse.co m
>>>>
>>>>
>>>"Danie l Bass" <da***********@ blueCAPSbottle. comFIRSTwrote in
>>>messag e news:u8******** ******@TK2MSFTN GP03.phx.gbl...
>>>>Greetin gs!
>>>>>
>>>>I'm trying to call this method in a c# app...
>>>>>
>>>> SNAPIDLL_API int __stdcall SNAPI_SetCapabi litiesBuffer(HA NDLE
>>>>DeviceH andle, unsigned char *pData, long max_length);
>>>>>
>>>>So far I've got this:
>>>> [DllImport("Depe ndencies\\SNAPI .DLL")]
>>>> public static extern int SNAPI_SetVersio nBuffer(IntPtr
>>>>DeviceH andle, StringBuilder pData, long max_length);
>>>>>
>>>>Keep getting a PInvokeStackImb alance error and I think it's the
>>>>2nd paramter pData because I've referenced the device handler and
>>>>the long typedef is pretty obvious.
>>>>>
>>>>For the 2nd paramter I've tried the following without success:
>>>> byte[]
>>>> char[]
>>>> string
>>>> StringBuilder
>>>> [MarshalAs(Unman agedType.AnsiBS tr)] string
>>>>>
>>>>HELP!
>>>>Thank s.
>>>>Dan.
>>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>




Oct 23 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
10681
by: TT (Tom Tempelaere) | last post by:
Hi people I am wrapping a C dll using PInvoke from C#. I need to wrap the following signature in C int dma_start( const UCHAR* data, UINT data_length ) The function should start with a DMA operation, and I have to use it from my C# program. I am really unsure what type of marshalling I should use. The data parameter is a pointer to an array of byte data. This data must not be copied when calling the function. Plus, the .NET...
2
3564
by: John Smith | last post by:
Hello :) I have a DLL file written in C where one function accepts an array of structures as input paramter and pointer to length integer. This function will fill up the array and specify the number of items set. In other words the prototype looks like: void Func(mystruct *pStruct, int *npLength); I would like to call this from C# but I'm having a lot of trouble getting it to accept this array as parameter.
0
1059
by: Dgdege | last post by:
Hi all, I want to wrapp an exiting API written in C++ to .NET using managed C++ extensions. I want my managed C++ class library to link with the unmanaged dll. So I don't use PInvoke for marshalling data's. I don't want to wrapp some basic classes but rather re-write then into managed C++ code. Let say I have a basic class named Vec3f which stores 3 floating values. I re-write this class in managed C++ using
6
2261
by: Mythran | last post by:
struct MyStruct { public int Number; } struct MyStruct { private int mNumber; public int Number
7
3477
by: Asfar | last post by:
I have a MFC dll in which one of the parameters is of LPSTR. The declaration of my MFC dll looks like extern "C" __declspec(dllexport) int WINAPI EXPORT TestPInvokeFunc(LPSTR szFileName, LPSTR szResult) { char resultchar; //some processing which put the result values in resultchar strcpy(szResult, &resultchar); return 0;
1
2558
by: Beorne | last post by:
I have a cpp application with this structure: //////////////C++/////////////// typedef struct StatusStructure { char FixedLenString; long LongVariable; double DoubleVariable; BOOL BoolVariable; } StatusStructure;
4
2435
by: Beorne | last post by:
I have to call a c++ library funtion with the following signature: void ReadBool(bool* pb1) unsafe static extern void NicamPLCRead(out bool); but this does not work, the bool (not initialized) is not correctly returned.
2
4951
by: Beorne | last post by:
I have to call a c++ library funtion returning a string with the following signature: char *get_identifier(); Usually when I have to marshal a function with a char* output parameter I do: static extern int get_identifier2( StringBuilder Ack_Msg, int msg_len);
3
5264
by: Beorne | last post by:
I have a propertary library dll (used to drive a device) that I call from my C# code. Calling the functions from C++ is really faster than calling them in C+ +. From C++ the call is almost instantaneous, from C# is about 1.5 seconds long. For example, this command powers a device based on an interface switch and returns a message in Ack_Msg that is len long. Besides returns an error code.
0
1071
by: Aldev | last post by:
Hi There, I am quite new to PInvoke and calling COM functions from C#. I have managed so far to call some unmanaged functions ib my C++ dll from my C# code but at the moment I am having trouble with one particular function. I have a sample of the function being correctly defined in some VB6 code below.
0
8888
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9401
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9174
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9111
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8096
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6702
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
2634
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.