# [.net] How to PInvoke function within a dll

This topic is 4240 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello Everyone, I need to PInvoke function within a dll, the function signature is (for example): BOOL Foo( PVOID inA, DWORD inB, PVOID outC, DWORD outD, PDWORD outE ); I tried this (C#), with no success : [DllImport("aa.dll")] static extern bool Foo( IntPtr inA, UIntPtr inB, [Out] byte[] outC, UIntPtr outD, IntPtr outE ); Where did I go wrong ? Thanks ! [Edited by - LessBread on June 7, 2006 3:06:51 PM]

##### Share on other sites
What do you mean 'no success'? It looks plausible, but I have no experience of PInvoke really so I wouldn't know if it was wrong.

##### Share on other sites
I'm getting access violation while trying to execute (P-Invoke) this function.
It may be the way I set up values to the parameters,
But first I would like to know if I wrote the "static extern ..." signature currectly..

##### Share on other sites
I haven't used PInvoke using C# yet (only VB.NET) so I can't tell you if the signature is right. But you might want to check out PInvoke.NET. It's a wiki dedicated to PInvoke. I'm sure you'll find what you need there

##### Share on other sites
Thanks, but this site is only for known dll's..

##### Share on other sites
Try this:
static extern Int32 Foo(IntPtr inA,Int32 inB,out IntPtr outC,Int32 outD,out Int32 outE);

A BOOL is really an integer, not a bool (although it might still work with a bool instead of Int32). If you know the actual types of inA and outC, you should be able to define sequential layout structures for those and pass them directly, rather than using IntPtr. Note that "outD" implies an output parameter, but it's signature isn't a pointer, so it can't be a pointer.

Without the "real" signature (what do the parameters represent and how are they used) it's hard to provide a useful declaration. For example, if outD specifies how many DWORD values outE can hold, then you have a completely different ballgame than if outE is just a pointer to a single DWORD...

##### Share on other sites
Hi Dave,

1.What do you mean by "Real signature" ?
isn't it the real signature ?

BOOL Foo(
PVOID inA,
DWORD inB,
PVOID outC,
DWORD outD,
PDWORD outE
);

BTW: I'm trying to invoke the function LmPrinterIoControl
fro here :
http://www.swecoin.se/CustomFiles/TTP%20Language%20Monitor%20Implementation.pdf

2. What's the difference between "out" and "ref" ?

Thanks again !

##### Share on other sites
By "real signature" I meant "what do the parameters represent." With the document you provided, I now have what I need.

You'll need to do something like this:
// declarationpublic static extern int LmPrinterIoControl([In] byte[] inBuffer,Int32 inBufferSize,[In,Out] byte[] outBuffer,Int32 outBufferSize,ref Int32 bytesReturned);// usagebyte[] inBuffer = new byte[inBufferSize];// don't know where data in inBuffer comes from, assume it's filled at this point.byte[] outBuffer = new byte[outBufferSize];LmPrinterIoControl(inBuffer,inBufferSize,outBuffer,outBufferSize,ref bytesReturned);

I don't have any way of verifying this, but it looks ok.

edit:
To answer question #2, "out" says I'm not going to initialize this variable, so don't read it, just set it. "ref" says the variable can be both read and written.

Note that this is different from In,Out in brackets, which has to do with how the PInvoke marshals the variables between the caller and the called.

##### Share on other sites
Thanks Dave, I will check it out !

btw: This function needs to send block of data to the printer,
and get a block of data (the answer).

For example, the block that been sent may ask for the printer status,
and the received block may contain and answer (out of paper, hot printer, etc.)

I read the pdf file, but I couldn't figure out the protocol,
which bytes array I need to send, in order get the answer ?

can you understand it from the document ?

Thanks !!

##### Share on other sites
It looks to me like you need to set the inBuffer to the sequence of bytes shown in the TTPKEY structure. For example, to get the "General Status", you would set inBuffer to the sequence of bytes corresponding to

"\x1b\x05\x01", 3, 2, REG_BINARY, TEXT("Status General")

I don't know how the TTPKEY structure is defined, so I have no idea how long each field is. If you've got a header file for the API, you should be able to figure that out. You could write a C program that outputs the sequence of bytes for each command. That way you could see exactly what bytes you need for a particular command.

The return buffer (outBuffer) will contain a series of bytes corresponding to the values shown in the table under "Remarks". Again, I don't know exactly how those will appear, so you might write a C program to check that out as well.

##### Share on other sites
Hi,

I don't have the header file, and I don't know C,
So I guess I will have to try handle only with the DLL and documentation.

You wrote about the "Status General", white belongs to the "getPrinterData" function, but the only function I can use is "LmPrinterIoControl" function,
And I can't understand from this function table which data I need to send,
In order to get relevant data...

It's just me, or you also can't understand from the "LmPrinterIoControl" documentation which data to send ? :-)

btw: If it can help, I uploaded the DLL file to :

Thanks again !

##### Share on other sites
According to the document, getPrinterData is just a wrapper around LmPrinterIoControl that sends the appropriate bytes from the table. So, calling getPrinterData with a TTPCommand of TTPKEY_STATUS_GENERL would send the bytes in the table that I showed in my previous post.

There is a download available on their site that contains sample C++ source code. In that download are the TTP.H and TTP.CPP files that define all of the TTPKEY stuff. The TTPKEY structure is defined as:
typedef struct _TTPKEY {	BYTE	cmd[4];	DWORD	inLen;	DWORD	outLen;	DWORD	type;	TCHAR	name[256];} TTPKEY, *PTTPKEY;

So, to send the command to get the general status you would need to send the bytes I showed as they are defined above.
cmd                   inLen                 outLen                type (REG_BINARY)0x1b,0x05,0x01,0x00,  0x03,0x00,0x00,0x00,  0x02,0x00,0x00,0x00,  0x08,0x00,0x00,0x00,name'S','a','t','u','s',' ','G','e','n','e','r','a','l' (followed by enough zeros to make this field 256 bytes long)

That's about all the help I can offer.

##### Share on other sites
Thanks Dave,

But the documentation says about the "GetPrinterData" function :
"This function should currently only be used with parallel printer."

For this reason (and some more),
I need to work directly with the "LmPrinterIoControl" function.

The problem is not the code, but the table understanding :-)
Can you figure out from the "LmPrinterIoControl" table (parameters and values),
what should I send inside the bytes array, in order to get the information ?

##### Share on other sites
As near as I can tell, the bytes I gave in my previous post are what you would send to LmPrinterIoControl as the inBuffer parameter. Whether this works with anything other than a parallel printer is unclear from the documentation. But I get the impression that the command bytes are the same.

##### Share on other sites
I just read through the sample code and I think I've got it now.

You only need to send the bytes from the cmd field. So, to send the general status request, you would send the following bytes in inBuffer:
0x1b,0x05,0x01

and specify 3 for the inBufferLen parameter.

Then you will get back a sequence of bytes in the outBuffer representing the status. The PDF document didn't display correctly for me, so I couldn't figure out how to interpret the return bytes.

At any rate, that should get you going.

##### Share on other sites
Thanks Dave !

Just a little remark :
when you said "from the cmd field", what excatly did you mean ?
Is there a cmd field/column in the table ?

Maybe you refer to this line (in your example) ? :
{ "\x1b\x05\x01", 3, 2, REG_BINARY, TEXT("Status General")},

But this example is not of the "LmPrinterIoControl" function..
DO you think is doesn't matter, and I should send thie sequence of bytes while using the "LmPrinterIoControl" function ?

Thanks.

##### Share on other sites
From the sample app in the download I mentioned, the table shows what will be sent to LmPrinterIoControl by GetPrinterData based on the command id.

The cmd field is the first field in the TTPKEY command structure. Those are the bytes that need to be sent to LmPrinterIoControl in the inBuffer field.

inLen is the second field in the TTPKEY command structure. That field is the value that needs to be sent to LmPrinterIoControl in the inBufferLen field (it specifies how many bytes are in the inBuffer field).

The third field in the TTPKEY command structure is outLen. It specifies how many bytes will be returned for that command in the outBuffer field. So you would pass that to LmPrinterIoControl in the outBufferLen field and make sure that your outBuffer was at least that big.

The fourth and fifth fields in the TTPKEY command structure (type and name) are informational and give the type of the returned data (REG_BINARY) and a textual description of the command.