Click here to Skip to main content
15,885,877 members
Please Sign up or sign in to vote.
4.47/5 (8 votes)
See more:
Hi,

I am a C/C++ programmer, but I was asked to update a program that was written in C# to communicate with a device. My knowledge of C# is very basic. The previous version was totally written in C#, but now the API that in fact access the device was changed to C. I found out that I can import the C function APIs by using:

[DllImport("myapi.dll")]
public static extern int myfunct( 
                                 [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
                                 IntPtr hpDevice);


In C this function prototype is:

int myFunct( LPTStr lpDeviceName, HANDLE* hpDevice );


Where HANDLE is defined as :

typedef void *HANDLE;


However this function does not work as expected. In fact, in the C# code call what kind of type I should declare and pass to the C# method?

// Later edit I aplogize for the fake answer.

I am facing a new problem now. I have a C structure like:

struct MyStruct
{  unsigned char* ptr;  
int ptr_size;}


This pointer filled with values by a C API function, thus in C I only pass to the function a buffer large enough to hold the data.
To convert this to C# way I can do:

[StructLayout(LayoutKind.Sequential)]
public class MyStruct
{  IntPtr ptr;// this is a pointer to a buffer that will  
   int size;  // be filled with values by the C API
};// Next I instantiate itMyStruct ms = new MyStruct();



Now, the odd part comes in. I have a simple C# array as :

byte[] RESET = new byte[]{ 0x00, 0x00, 0x80, 0x00};


OK, now ptr must point to RESET, so how could this be done? Ptr needs to hold the address it self....
Thanks a lot for the help!
Posted
Updated 21-Jul-10 2:50am
v2

Well your code would appear to be correct, I suspect the problem is more likely to be with the actual values of the parameters that you are passing to the C routine. Try using the debugger or add some logging code to verify your parameters.
 
Share this answer
 
Comments
Nish Nishant 17-Jul-10 7:42am    
Reason for my vote of 5
Worth 5.
danielgomes 19-Jul-10 7:36am    
Hey Thanks for the help! I "over debbugued it" already :-). I made it work by writting a "bridge" DLL which made all the things, but my boss reject it as he wants me to do all the thing in C# :-(
In my (limited) experience there are three potential issues here.

1. As Richard suggested - are you using correct values for the parameters? Particularly hpdevice. Is this a pointer that you have previously retrieved from another unmanaged function call? If not, that could be your issue.

2. Strings with P/Invoke can be troublesome. Try using a System.Text.StringBuider instead as it has built in marshalling capabilities.
C#
[DllImport("myapi.dll")]
public static extern int myfunct(
    StringBuilder lpDeviceName,
    IntPtr hpDevice);


3. Unlikely but is hpDevice supposed to be a pointer to a pointer? This happens alot in C/C++ and it's a pain sometimes to work out what's going on.
 
Share this answer
 
v2
Comments
Nish Nishant 17-Jul-10 7:42am    
Reason for my vote of 5
Good answer, and worth 5.
danielgomes 19-Jul-10 7:42am    
Reason for my vote of 5
It was StringBuilder!
DaveyM69 19-Jul-10 16:10pm    
Glad you got it sorted! Strings are pesky little buggers as in .NET they are not null terminated char arrays as they are in C/C++ so pointers from the managed world are often not valid as string pointers in the unmanaged world even when using the MarshalAs attribute. StringBuilder has all this stuff taken care of deep down inside fortunately.

To question 2


The problem with your byte[] is it can be moved around in memory. To stop that you would need to pin RESET. Have a look at the GCHandle structure inparticular:
GCHandle.Alloc(object, GCHandleType.Pinned) and DON'T FORGET to use
GCHandle.Free() when done with it, and to get the pointer
GCHandle.AddrOfPinnedObject().
 
Share this answer
 
Comments
danielgomes 20-Jul-10 10:26am    
Reason for my vote of 5
Thanks that helped me!
danielgomes 20-Jul-10 10:29am    
It was kind of "tricky" but it worked in the end. Specially I had to instantiate the struct above statically ( i.e. do not use new ) otherwise it will always pass an address to the function and it already passes a reference ( ref keyword ) so it won't work unless it is static.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900