我正在尝试使用封送处理在我的C#项目中调用C DLL,并且某些功能可以工作,但是我遇到了其他麻烦。像下面的那个。
我的第一个问题是使结构正确,下一个问题是将PROFILE_INFO作为包含程序文件列表的数组返回,或者可能不会返回列表,而proNum是索引。
C中的功能
extern "C" __declspec(dllexport) int WINAPI GetProgramFileList (unsigned long proNum, PROFILE_INFO *proFile);
typedef struct{
PROINFO proInfo;
__int64 proSize;
PROGRAM_DATE createDate;
PROGRAM_DATE writeDate;
}PROFILE_INFO;
typedef struct{
char wno[33];
char dummy[7];
char comment[49];
char dummy2[7];
char type;
char dummy3[7];
}PROINFO;
typedef struct{
short year;
char month;
char day;
char hour;
char min;
char dummy[2];
}PROGRAM_DATE;
我的功能
[DllImport(@".\IFDLL.dll", EntryPoint = "GetProgramFileList", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
public static extern int GetProgramFileListTest(ulong proNum, ref PROFILE_INFO pro);
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct PROFILE_INFO
{
[MarshalAs(UnmanagedType.Struct)]
public PROINFO proInfo; // WNo/name/type
public long proSize; // Program size
[MarshalAs(UnmanagedType.Struct)]
public PROGRAM_DATE createDate; // Program creating date
[MarshalAs(UnmanagedType.Struct)]
public PROGRAM_DATE writeDate; // Program updating date
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct PROINFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string wno; // WNo.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy; // dummy
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 49)] public string comment; // program name
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy2; // dummy
public char type; // program type
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy3; // dummy
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct PROGRAM_DATE
{
public short year; // Date (Year) 4-digit
public char month; // Date (Month)
public char day; // Date (Day)
public char hour; // Date (Time)
public char min; // Date (Minutes)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] private char dummy; // Dummy
}
C#结构PROFILE_INFO中的PROGRAM_DATE createDate将抛出:
无法封送类型为'CClient.Models.PROFILE_INFO'的字段'createDate':此字段的类型定义具有布局信息,但是托管/非托管类型组合无效或不可编组。
将PROGRAM_DATE字段更改为字符串可以使其接受字符串,但是该函数将返回参数(-60)错误。尽管不确定我是否更接近成功。
其他尝试,包括尝试获取PROFILE_INFO以数组形式返回(参考PROFILE_INFO []),
对PInvoke函数的调用使堆栈不平衡。这可能是因为托管PInvoke签名与非托管目标签名不匹配。
我在C dll之后有这些描述:
说明
在标准区域中获取程序列表
参数
proNum [in]
指定要获取的数据数。
proFile [输出]
以PROFILE_INFO类型将程序信息存储在标准区域中。
执行此功能之前,请确保确保要获取的数据数量所在的数据区域。
返回值
如果成功,则返回“ 0”。如果有错误,则返回“ 0”以外的值。
我正在使用的其他函数是GetProgramDirInfo,SendProgram,ReceiveProgram,SearchProgram等,但是它们不返回任何数组,因此我认为在这里处理数组是我的问题。另外,我试图避免使用不安全的指针,并且不确定是否需要自己复制。
感谢您的帮助。
答案 0 :(得分:0)
使用p /调用时的几点注意事项:
pack
,在默认情况下,.NET的行为应类似于C / C ++ int
和long
通常是32位。 long
在C / C ++中不是64位这是一个更好的代码:
[DllImport(@".\IFDLL.dll", EntryPoint = "GetProgramFileList")]
public static extern int GetProgramFileListTest(uint proNum, ref PROFILE_INFO pro);
[StructLayout(LayoutKind.Sequential)]
public struct PROFILE_INFO
{
public PROINFO proInfo; // WNo/name/type
public long proSize; // Program size
public PROGRAM_DATE createDate; // Program creating date
public PROGRAM_DATE writeDate; // Program updating date
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PROINFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string wno; // WNo.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy; // dummy
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 49)] public string comment; // program name
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy2; // dummy
public char type; // program type
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] private string dummy3; // dummy
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PROGRAM_DATE
{
public short year; // Date (Year) 4-digit
public char month; // Date (Month)
public char day; // Date (Day)
public char hour; // Date (Time)
public char min; // Date (Minutes)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] private string dummy; // Dummy
}