C++中char[]型数据对应C#中的哪一种类型,我用的byte[]代替,但还是有点问题

docker_007 2020-04-05 05:46:45
我在C#里面调用C++DLL的接口函数,函数里面有个
参数是结构体指针,详情请见下面代码。我是用的byte[]来对应
C++中的char[](结构体里面的成员变量数据类型),编译可以通过。
但是调试的时候打断点跟进发现,在C#代码中,ST_FILENAME_PACK 类型
的参数的数据还是有效的,但是进入到C++的调用函数之后,
结构体ST_FILENAME_PACK的成员变量的内容就变成了无效字符(详情见附图)。
以前没用过C#,网上找了一下午也没搞明白在这里应该怎么做数据类型转换。


else if (btn.Name == "PackBtn")
{
int PacFileLength = 0;
ST_FILENAME_PACK[] stFilePacList = new ST_FILENAME_PACK[3];

stFilePacList[0].sSrcFileName = System.Text.Encoding.Default.GetBytes(TextBox5.Text);
stFilePacList[0].sDstFolderPath = System.Text.Encoding.Default.GetBytes("E:\\Temp\\t3");

stFilePacList[1].sSrcFileName = System.Text.Encoding.Default.GetBytes(TextBox6.Text);
stFilePacList[1].sDstFolderPath = System.Text.Encoding.Default.GetBytes("E:\\Temp");

stFilePacList[2].sSrcFileName = System.Text.Encoding.Default.GetBytes(TextBox7.Text);
stFilePacList[2].sDstFolderPath = System.Text.Encoding.Default.GetBytes("E:\\Temp\\t3");

string PacName = TextBox8.Text;
if ( ( PacFileLength = DoPack2(ref stFilePacList, 3, PacName, 1) ) < 0 )
{
MessageBox.Show("DoPack Error");
}
}


结构体ST_FILENAME_PACK在C#中的定义:
    
public struct ST_FILENAME_PACK
{
public byte[] sSrcFileName;
public byte[] sDstFolderPath;
}


结构体ST_FILENAME_PACK在C++中的定义:

#define MAX_PATH 260
typedef struct
{
char sSrcFileName[MAX_PATH];
char sDstFolderPath[MAX_PATH];
} ST_FILENAME_PACK;


函数DoUnpack2在C++中的原型

int DoPack2(ST_FILENAME_PACK *pstFilenamePackList, int nSrcFileNameNumber, char *pPackFileName, int nPackSubFoderFlag);

函数DoUnpack2在C#中的声明

public extern static int DoPack2(ref ST_FILENAME_PACK[] pstFilenamePackList, int nSrcFileNameNumber, string pPackFileName, int nPackSubFoderFlag);






...全文
858 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
docker_007 2020-04-06
  • 打赏
  • 举报
回复
谢谢啦!问题搞定了! 1.结构体ST_FILENAME_PACK里面成员变量最后是采用string来封送的。 2.在那个结构体指针参数的属性卡了很久,如果用in属性,结构体传入C++之后,结构体内部数据是乱码或者无效字符(至于是什么原因,目前还没搞明白)。最后参考了下面第1条参考链接的回答,改用[In,Out]属性,问题解决。 参考链接: 1.https://social.microsoft.com/Forums/de-DE/129a9d68-fa73-4d7e-ae12-182f562afedc/c-interop-passing-array-of-struct-to-a-dll的最后一条评论 2.https://stackoverflow.com/questions/188299/marshal-c-struct-array-into-c-sharp 最后的代码是这样的: 结构体ST_FILENAME_PACK在C#中的定义:

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct ST_FILENAME_PACK
    {
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string sSrcFileName;
        
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string sDstFolderPath;
    }
函数DoUnpack2在C#中的声明:

[DllImport("xxxx.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public extern static int DoPack2([In, Out] ST_FILENAME_PACK[]  pstFilenamePackList, int nSrcFileNameNumber, string pPackFileName, int nPackSubFoderFlag);
变量stFilePacList的赋值过程和DoPack2的传参过程如下:

int PacFileLength = 0;
                ST_FILENAME_PACK[] stFilePacList = new ST_FILENAME_PACK[3];

                stFilePacList[0].sSrcFileName = TextBox5.Text;
                stFilePacList[0].sDstFolderPath = "E:\\Temp\\t3";

                stFilePacList[1].sSrcFileName = TextBox6.Text;
                stFilePacList[1].sDstFolderPath = "E:\\Temp\\t3";

                stFilePacList[2].sSrcFileName = TextBox7.Text;
                stFilePacList[2].sDstFolderPath = "E:\\Temp\\t3";

                string PacName = TextBox8.Text;
                if ( ( PacFileLength = DoPack2( stFilePacList, 3, PacName, 1) ) < 0 )
                {
                    MessageBox.Show("DoPack Error");
                }
wanghui0380 2020-04-05
  • 打赏
  • 举报
回复
用byte[] 这样的方式去定义结构体,需要指明大小,不然这种不定长的东西在封送的时候无法确定zise public struct ST_FILENAME_PACK { [这里有个特性标记,标记封送类型和大小,自己百度一下C# pinvoke的资料,东西太杂,我懒得记具体代码] public byte[] sSrcFileName; public byte[] sDstFolderPath; }
wanghui0380 2020-04-05
  • 打赏
  • 举报
回复
在C#里做Pinvoke 交互封送时char[]是根据情况选择 in方式 ----------------采用string out方式----------------采用stringbuiler 当然还有一个通用方式 inptr,这个就是指针封送。反正到C++里 实际要的就是指针。所以用inptr也行,就是使用上麻烦点。
wanghui0380 2020-04-05
  • 打赏
  • 举报
回复
额,作为in参数,你干嘛要ref。 源文件名,目标路径-------我们干嘛要修改他,既然不修改const 就好

111,105

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧