如何将 Stucture 的地址传递给 C# 中的 Void 指针 [void*] 到 VC++ Dll

Posted

技术标签:

【中文标题】如何将 Stucture 的地址传递给 C# 中的 Void 指针 [void*] 到 VC++ Dll【英文标题】:How to Pass address of Stucture to Void pointer[void*] in C# to VC++ Dll 【发布时间】:2014-08-04 04:47:21 【问题描述】:

//结构:

struct MYDATA
char calls[4069];      
char Desc[4096];   
char error[1024];     

 ;

//测试函数

char *Argv[] =  "ToolName", "USername", "192.168.2", "3", "400";  
typedef void* ( *__stdcall  pCstartSIPSessionint)(char **argv ); 
typedef struct MYDATA*(*__cdecl pgetStat) ();

pCstartSIPSessionint startSessionint = (pCstartSIPSessionint )GetProcAddress(HMODULE (hGetProcIDDLL),"startSessionint"); 

//DLL导入

HINSTANCE hGetProcIDDLL = LoadLibrary(TEXT("E:\\MyDll.dll"));

pgetStat getStat ;
getStat = (pgetStat ) startSessionint(Argv);

MYDATA *mydata;
if(getStat != NULL)
        mydata= getStat();
printf("\n mydata\n %s ", mydata->call); 
printf("\n mydata\n %s ", mydata->summary); 
printf("\n mydata\n %s ", mydata->error);

如何转换 C# 中的代码? 而且我很困惑将结构的地址传递给 C# 中的 Void* 我只能传递值,如何将地址传递给结构。

提前谢谢...!

【问题讨论】:

"这很有帮助,但我用一些行来构造......如果我没有运行时间,我的事情 intptr 具有相同的内存地址......我可以知道 y – user3322182 "......你会必须向我们展示“回调/委托”函数内部的内容......以确定为什么它总是返回相同的指针。 【参考方案1】:

结构应该是:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MYDATA

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4096)]
    public string calls;      
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4096)]
    public string Desc;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
    public string error;     

我认为问题中的 4069 值是错字。

第一个函数是:

[DllImport(dllname, CharSet = CharSet.Ansi)] 
public static extern IntPtr startSessionint(string[] argv);

然后将函数指针转换为委托:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr getStatDelegate();
....
IntPtr ptr = startSessionint(argv);
if (ptr == IntPtr.Zero)
    // handle error
getStatDelegate getStat = (getStatDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(getStatDelegate));

现在你可以调用函数了:

IntPtr structPtr = getStat();

然后编组到结构体:

MYDATA data = (MYDATA)Marshal.PtrToStructure(structPtr, typeof(MYDATA));

【讨论】:

它工作但它抛出警告/错误,如 ------- @Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'c:\users\vts\documents\visual studio 2013 \Projects\AppNew\AppNew\bin\Debug\AppNew.exe'。附加信息:对 PInvoke 函数 'AppNew!AppNew.Form1::startSessionint' 的调用使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。提前致谢 好吧,也许 startSessionint 真的是 cdecl。 我敢打赌它真的是 cdecl。你有实现吗? 这里工作正常。一周过去了。我不知道你的代码现在是什么样子。我想我已经回答了你提出的问题。 没关系。我不能再提供了。我回答了你提出的问题。

以上是关于如何将 Stucture 的地址传递给 C# 中的 Void 指针 [void*] 到 VC++ Dll的主要内容,如果未能解决你的问题,请参考以下文章

如何将 C# 中的二维数组传递给 C++ DLL?

如何将指向 C# 结构的指针传递给 C 中的方法

如何将 C# 中的方法指针传递给 C 库?

如何将xml传递给C#中的View?

如何将值收集到数组中并将集合传递给 C# 中的 datagridview?

如何将C#数据表传递给mysql的存储过程参数