首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将C#结构配置为C++变体

将C#结构配置为C++变体
EN

Stack Overflow用户
提问于 2013-10-31 15:06:35
回答 2查看 2K关注 0票数 1

首先,我对COM技术不太熟悉,这是我第一次用它来忍受我自己。我正在尝试从C#调用一个COM对象函数。

这是idl文件中的接口:

代码语言:javascript
复制
[id(6), helpstring("vConnectInfo=ConnectInfoType")] 
HRESULT ConnectTarget([in,out] VARIANT* vConnectInfo);

这是我在运行tlbimp之后获得的interop接口:

代码语言:javascript
复制
    void ConnectTarget(ref object vConnectInfo);

COM对象中的目标函数的c++代码:

代码语言:javascript
复制
STDMETHODIMP PCommunication::ConnectTarget(VARIANT* vConnectInfo)
{
    if (!((vConnectInfo->vt & VT_ARRAY) && (vConnectInfo->vt & VT_BYREF)))
    {
        return E_INVALIDARG;
    }

    ConnectInfoType *pConnectInfo = (ConnectInfoType *)((*vConnectInfo->pparray)->pvData);
...
}

此COM对象在另一个进程中运行,它不在dll中.

我可以补充说,COM对象也来自用C++编写的另一个程序。在这种情况下,没有问题,因为在C++中创建了一个变量,并且pparray->pvData被设置为connInfo数据结构,然后以变量作为参数调用COM-对象。

在C#中,正如我所理解的那样,我的结构应该被自动编组为一个变体。

这是我一直在使用的两种方法(或者实际上我尝试了更多.)要从C#调用此方法:

代码语言:javascript
复制
    private void method1_Click(object sender, EventArgs e)
    {
        pcom.PCom PCom = new pcom.PCom();
        pcom.IGeneralManagementServices mgmt = (pcom.IGeneralManagementServices)PCom;
        m_ci = new ConnectInfoType();
        fillConnInfo(ref m_ci);
        mgmt.ConnectTarget(m_ci);
    }

在上述情况下,结构被编组为VT_UNKNOWN。这是一个简单的情况,如果参数不是一个结构(例如。为int工作)。

代码语言:javascript
复制
    private void method4_Click(object sender, EventArgs e)
    {
        ConnectInfoType ci = new ConnectInfoType();
        fillConnInfo(ref ci);

        pcom PCom = new pcom.PCom();
        pcom.IGeneralManagementServices mgmt = (pcom.IGeneralManagementServices)PCom;

        ParameterModifier[] pms = new ParameterModifier[1];
        ParameterModifier pm = new ParameterModifier(1);
        pm[0] = true;
        pms[0] = pm;
        object[] param = new object[1];
        param[0] = ci;
        object[] args = new object[1];
        args[0] = param;
        mgmt.GetType().InvokeMember("ConnectTarget", BindingFlags.InvokeMethod, null, mgmt, args, pms, null, null);
    }

在本例中,它被编组为VT_ARRAY _ VT_BYREF _VT_BYREF_ VT_VARIANT。问题是,在调试“目标函数”ConnectTarget时,我无法找到我在SAFEARRAY-struct中发送的数据(或者在内存中的任何其他地方)。

我该怎么处理VT_VARIANT?

对如何得到我的结构数据有什么想法吗?

更新:

ConnectInfoType结构:

代码语言:javascript
复制
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class ConnectInfoType
    {
        public short network;
        public short nodeNumber;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 51)]
        public string connTargPassWord;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string sConnectId;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string sConnectPassword;
        public EnuConnectType eConnectType;
        public int hConnectHandle;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string sAccessPassword;
    };

以及c++中相应的结构:

代码语言:javascript
复制
typedef struct ConnectInfoType
{
    short network;
    short nodeNumber;
    char connTargPassWord[51];
    char sConnectId[8];
    char sConnectPassword[16];
    EnuConnectType eConnectType;
    int hConnectHandle;
    char sAccessPassword[8];
} ConnectInfoType;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-05 15:50:06

我找到了一个可以接受的解决办法/解决办法。我将结构转换为字节数组,然后将接收到的数据转换为ConnectInfoType结构。

代码语言:javascript
复制
    // C#
    private void method3_Click(object sender, EventArgs e)
    {
        pcom.PCom PCom = new pcom.PCom();
        pcom.IGeneralManagementServices mgmt = (pcom.IGeneralManagementServices)PCom;
        ConnectInfoType ci = new ConnectInfoType();
        fillConnInfo(ref ci);

        IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ci));
        Marshal.StructureToPtr(ci, ptr, false);
        byte[] arr = new byte[Marshal.SizeOf(ci)];
        Marshal.Copy(ptr, arr, 0, Marshal.SizeOf(ci));

        mgmt.ConnectTarget(arr);
    }

这将被编组为VT_ARRAY |VT_UI1,因此我已经将c++代码更改为:

代码语言:javascript
复制
// C++
STDMETHODIMP PCommunication::ConnectTarget(VARIANT* vConnectInfo)
{
    if (!((vConnectInfo->vt & VT_ARRAY) && (vConnectInfo->vt & VT_UI1)))
    {
        return E_INVALIDARG;
    }

    ConnectInfoType *pConnectInfo = (ConnectInfoType *)(vConnectInfo->parray->pvData);
...
}

如果有人知道更好的解决方案,可以随意添加。

票数 0
EN

Stack Overflow用户

发布于 2013-11-05 12:09:10

使用这个类http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.variantwrapper%28v=vs.110%29.aspx包装它,然后调用所需的方法。

你能发布"ConnectInfoType“类型的ConnectInfoType源代码吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19710072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档