calling dll function with struct like this (I think I may have possible solution)

A

Angel

Hello again (and again, and again...)
I think I'm getting closer to solving my initial problem of calling
unmanaged code. I managed to call the functions with user-defined structs
w/o getting any run-time exceptions. The problem is that I'm receiving a
Failure return (it returns 1 = "Failure"). I have a feeling it may be that
the function's not reading the struct correctly.

This time I decided to display all the code (it's very short). The original
struct declared in the .h looks like this:

typedef struct
{
char detail_code; /* copyright detail code */
char zip_code[5+1]; /* zip code */
char city_key[6+1]; /* city/state key */
} CITY_REC;

The original function syntax is:
int z4ctynxtSTD (CITY_REC *city_rec); //STD for stdcall calling
convention

The struct I converted it to: (in another cs file which only has this
struct):

namespace ZM
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CITY_REC
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
public string detail_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string zip_code;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=7)]
public string city_key;
}
and the function call i converted to:
[DllImport("C:\\zm7\\Developm\\DLL\\W32.DLL")]
public static extern int z4ctynxtSTD(CITY_REC city); //I used ref but it
didn't work either
public static void getCity()
{
ZIP4_PARM_class zip4 = new ZIP4_PARM_class();
CITY_REC city = new CITY_REC();
int i = z4open();
i = z4ctynxtSTD(city); //I used ref but it didn't work either
MessageBox.Show ("result: " + i.ToString()); // it returns 1, which
is "Failure"
z4close();
}

Am I declaring the struct correctly and am I sending it as parameter
correctly? I'm pretty sure I'm almost done.

Thanks again (and again, and again, and again... :)) )
 
G

Guest

Hi Angel,

Thank you for posting in the community!

Based on my understanding, you P/invoke your unmanaged api, but failed.

================================
I think the problem should be the marshal encoding problem.

Please try to use UnmanagedType.LPStr to replace UnmanagedType.ByValTStr to
see if resolved your problem. Also, you should apply "ref" in your function
parameter, like this: public static extern int z4ctynxtSTD(ref CITY_REC
city)

If the problem still exist, I think you may first use pure C++ to invoke
this function to see if the problem is related to P/invoke

===============================
Please apply my suggestion above and let me know if it helps resolve your
problem.

Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
A

Angel

Thanks for your help.
The company that wrote the DLL sent me some code that calls the api from C#
and it works so I don't think it has anything to do with p/invoke.. I'm
trying it with another function (and another struct) and that's where I get
the problem.

Instead of recreating the C-style struct as a C#
struct, I decided to use it as a class. I think that it's at least
communicating with the dll. This is how my class looks like:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi) ]
public class city
{
public city()
{
}
//[MarshalAs(UnmanagedType.LPStr)]
[MarshalAs( UnmanagedType.ByValArray, SizeConst=5 )]
public char detail_code;
public char[] zip_code;
public char[] city_key;
public char zip_class_code;
public char[] city_name;
}

The original:
typedef struct
{
char detail_code;
char zip_code[5+1];
char city_key[6+1];
char zip_class_code;
char city_name[28+1];
} CITY_REC;


When I invoke the function, I receive the error: "Can not marshal field
detail_code of type ZM7.city: Invalid managed/unmanaged type combination
(chars must be paired with U1 or U2)". At least the error specifies a field
(detail_code) inside the class, which I think may be a good sign.

What could it be?
Thanks.
 
G

Guest

Hi Angel,

Thanks very much for your feedback.

In C# P/invoke, marshal C-style structure as C# structure almost has not
different as C# class. The different is that, C# structure is a value type,
while a C# class is a reference type. So parameter like "ref struct" can be
replaced with "class". This is the only difference.

So I think the problem has nothing to do with whether use class or
structure, the problem should still be the marshaling.

In another post of you "exporting function with parm pointer to struct", a
community member has provided you a suitable solution for marshal as class.

Note: please use that class in your code like this: z4ctynxtSTD(city inst),
do not add "ref" in the parameter.

Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top