471,321 Members | 1,756 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,321 software developers and data experts.

Calling C++ function from C#

I need to call the below function from a C# application. Having
problems converting it to C#. I think the BOOLs are just integers in
C#. I have tried char[] and string for the PAWDOBJKEY. I always get
"ERROR_BAD_PARAM" for a return value.

SHORT APIENTRY AwdApiInsertItemKey(
HWND hwndContainer,
PAWDOBJKEY pAwdObjParentKey,
PAWDOBJKEY pAwdObjKey,
BOOL fUpdateCount,
BOOL fLockFlag,
PVOID pReserved);

Parameters
hwndContainer: A handle to the container in which you want to
insert an item.
pAwdObjParentKey: A pointer to the key of an existing parent of
the item to be inserted. If NULL, the item is inserted at the root.
pAwdObjKey: A pointer to the key of the item to insert. A view
call is made to get all the needed information to insert the item.
fUpdateCount: This parameter is ignored.
fLockFlag: Specifies whether or not to lock the object on
insertion. True=Lock False=Don’t Lock.
pReserved: Reserved for future use; it should be NULL.
=================
AWDOBJKEY
Data that uniquely defines an AWD object. This data
distinguishes the object from other objects of the same type.
Typedef struct awdobjkey
{
CHAR crdattim [26];
CHAR recordcd;
CHAR crnode[2];
} AWDOBJKEY, *PAWDOBJKEY;

==============
Aug 19 '08 #1
4 1686
On Aug 19, 6:10*pm, cozumeldi...@comcast.net wrote:
I need to call the below function from a C# application. Having
problems converting it to C#. I think the BOOLs are just integers in
C#.
It will work, but you can also use "bool" just fine - it maps to 4-
byte WinAPI-style BOOL by default.
I have tried char[] and string for the PAWDOBJKEY. I always get
"ERROR_BAD_PARAM" for a return value.

* * SHORT APIENTRY AwdApiInsertItemKey(
* * * * * * * * * * *HWND hwndContainer,
* * * * * * * * * * *PAWDOBJKEY pAwdObjParentKey,
* * * * * * * * * * *PAWDOBJKEY pAwdObjKey,
* * * * * * * * * * *BOOL fUpdateCount,
* * * * * * * * * * *BOOL fLockFlag,
* * * * * * * * * * *PVOID pReserved);

* * Parameters
* * * hwndContainer: * *A handle to the container in which you want to
insert an item.
* * * pAwdObjParentKey: A pointer to the key of an existing parent of
the item to be inserted. If NULL, the item is inserted at the root.
* * * pAwdObjKey: * * * A pointer to the key of the item to insert. A view
call is made to get all the needed information to insert the item.
* * * fUpdateCount: * * This parameter is ignored.
* * * fLockFlag: * * * * * * * *Specifies whether or not to lock the object on
insertion. True=Lock False=Don’t Lock.
* * * pReserved: * * * * * * * *Reserved for futureuse; it should be NULL.
* =================
* * AWDOBJKEY
* * * Data that uniquely defines an AWD object. This data
distinguishes the object from other objects of the same type.
* * * Typedef struct awdobjkey
* * * * * * {
* * * * * * * CHAR crdattim [26];
* * * * * * * CHAR recordcd;
* * * * * * * CHAR crnode[2];
* * * * * * } AWDOBJKEY, *PAWDOBJKEY;
I don't see why you should use char[] or string for AWDOBJKEY, since
it's a struct. So you need to create a corresponding C# struct:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct ADWOBJKEY
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=26)]
string crdattim;

char recordcd;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=2)]
string crnode;
}

And then PAWDOBJKEY is just a pointer, which (if you want to avoid
pointers in C#) translates to a "ref" argument of the method:

short AwdApiInsertItemKey(
* * * * * * * * * * IntPtr hwndContainer,
* * * * * * * * * * *ref AWDOBJKEY pAwdObjParentKey,
* * * * * * * * * * *ref AWDOBJKEY pAwdObjKey,
* * * * * * * * * * *bool fUpdateCount,
* * * * * * * * * * *bool fLockFlag,
* * * * * * * * * * *IntPtr pReserved);

Depending on whether the C++ code also includes some #pragma pack
directives (or is compiled with the corresponding compiler options),
you might also need to set StructLayoutAttribute.Size on the struct
declaration.
Aug 19 '08 #2
Thank you for your reply. Your code almost does the trick. I can do a
trace on the C++ function and it looks to me that when the C++
function get the data it is a little off. I am sending
"2008-06-13-03.54.36.420704" for the crdattim, 'T' for the recordcd
and "01" for the crnode. The first trace below is from another
application that calls this function, the second from my app. Looks
like the last character in the 2 strings is messed up. the last
character of the 1st string is a "0" and the last character of the
second string is a "."

Any ideas?

Good call:
DATA: 56 bytes
56 49 45 57 41 43 42 4C 30 30 31 38 58 58 58 58
<VIEWACBL0018XXXX>
58 58 58 58 30 30 30 30 30 31 4C 32 30 30 38 2D <XXXX000001L2008-
>
30 36 2D 31 33 2D 30 33 2E 35 34 2E 33 36 2E 34 <06-13-03.54.36.4>
32 30 37 30 34 54 30 31
<20704T01 >

Bad call:
DATA: 56 bytes
56 49 45 57 41 43 42 4C 30 30 31 38 58 58 58 58
<VIEWACBL0018XXXX>
58 58 58 58 30 30 30 30 30 31 52 32 30 30 38 2D <XXXX000001R2008-
>
30 36 2D 31 33 2D 30 33 2E 35 34 2E 33 36 2E 34 <06-13-03.54.36.4>
32 30 37 30 30 54 30 00
<20700T0. >
Aug 21 '08 #3
On Aug 22, 12:42*am, cozumeldi...@comcast.net wrote:
Thank you for your reply. Your code almost does the trick. I can do a
trace on the C++ function and it looks to me that when the C++
function get the data it is a little off. I am sending
"2008-06-13-03.54.36.420704" for the crdattim, 'T' for *the recordcd
and "01" for the crnode
Oh, so those strings are fixed length and not null-terminated (since
you are passing 2 chars to a char[2], which leaves no space for a
terminating '\0').

. The first trace below is from another
application that calls this function, the second from my app. Looks
like the last character in the 2 strings is messed up. the last
character of the 1st string is a "0" and the last character of the
second string is a "."
.NET assumed C-style null-terminated strings, and therefore replaced
the last character with '\0' for both strings (a single char was
marshalled fine because it's not a string).
Unfortunately, it means that you cannot use string marshalling (it
always assumes null terminator), and will have to work directly with
byte arrays. So:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct ADWOBJKEY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=26)]
byte[] crdattim;

char recordcd;

[MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
byte[] crnode;
}

To convert .NET strings to byte arrays and back, you use
Encoding.GetBytes() and Encoding.GetString() methods. The default
system encoding is Encoding.Default (it will be the same as using
CharSet.Ansi in earlier declarations).
Aug 22 '08 #4
Thank you very much. It now works. You are a genius.

On Aug 22, 1:23 am, Pavel Minaev <int...@gmail.comwrote:
On Aug 22, 12:42 am, cozumeldi...@comcast.net wrote:
Thank you for your reply. Your code almost does the trick. I can do a
trace on theC++function and it looks to me that when theC++
function get the data it is a little off. I am sending
"2008-06-13-03.54.36.420704" for the crdattim, 'T' for the recordcd
and "01" for the crnode

Oh, so those strings are fixed length and not null-terminated (since
you are passing 2 chars to a char[2], which leaves no space for a
terminating '\0').

. The first trace below is from another
application that calls this function, the second from my app. Looks
like the last character in the 2 strings is messed up. the last
character of the 1st string is a "0" and the last character of the
second string is a "."

.NET assumed C-style null-terminated strings, and therefore replaced
the last character with '\0' for both strings (a single char was
marshalled fine because it's not a string).
Unfortunately, it means that you cannot use string marshalling (it
always assumes null terminator), and will have to work directly with
byte arrays. So:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]structADWOBJKEY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=26)]
byte[] crdattim;

char recordcd;

[MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
byte[] crnode;

}

To convert .NET strings to byte arrays and back, you use
Encoding.GetBytes() and Encoding.GetString() methods. The default
system encoding is Encoding.Default (it will be the same as using
CharSet.Ansi in earlier declarations).
Aug 22 '08 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by Muthu | last post: by
6 posts views Thread by jchao123 | last post: by
1 post views Thread by Jesse McGrew | last post: by
5 posts views Thread by Nick Flandry | last post: by
2 posts views Thread by Geler | last post: by
15 posts views Thread by dspfun | last post: by
11 posts views Thread by briankirkpatrick | last post: by
16 posts views Thread by teju | last post: by
reply views Thread by rosydwin | last post: by

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.