qq_27068451 2022-08-19 10:39 采纳率: 50%
浏览 192
已结题

C#调用C++结构体,以接口的形式

问题遇到的现象和发生背景

img

img

img

问题相关代码,请勿粘贴截图
#pragma once

using namespace System;
using namespace System::Runtime;
using namespace System::Runtime::InteropServices;
using namespace Autodesk::AutoCAD::Runtime;
using namespace Autodesk::AutoCAD::DatabaseServices;

#include "dynprops.h"

namespace Autodesk
{
    namespace AutoCAD
    {
        namespace Windows
        {
            namespace OPM
            {
                [InteropServices::Guid("d0f45feb-71d5-44ea-B1A0-6E2F27B2085D")]
                [InteropServices::InterfaceTypeAttribute(InteropServices::ComInterfaceType::InterfaceIsIUnknown)]
                [InteropServices::ComVisible(true)]
                public interface class IOPMPropertyExpander2
                {
                    // 获得元素值
                    // DISPID dispID
                    // IUnknown * pUnk
                    // DWORD dwCookie
                    // VARIANT * pVarOut
                    void GetElementValue(
                        [InteropServices::In] System::Int32 dispID,
                        [InteropServices::In, InteropServices::MarshalAs(InteropServices::UnmanagedType::IUnknown)] Object^ pUnk,
                        [InteropServices::In] System::UInt32 dwCookie,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::Struct)] interior_ptr< Object^> pVarOut
                    );

                    // 设置元素值
                    // DISPID dispID
                    // IUnknown * pUnk
                    // DWORD dwCookie
                    // VARIANT VarIn
                    void SetElementValue(
                        [InteropServices::In] System::Int32 dispID,
                        [InteropServices::In, InteropServices::MarshalAs(InteropServices::UnmanagedType::IUnknown)] Object^ pUnk,
                        [InteropServices::In] System::UInt32 dwCookie,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::Struct)] interior_ptr< Object^> VarIn
                    );

                    // 获取元素分组
                    // DISPID dispID
                    // IUnknown * pUnk
                    // short * groupingNumber
                    void GetElementGrouping(
                        [InteropServices::In] System::Int32 dispID,
                        [InteropServices::In, InteropServices::MarshalAs(InteropServices::UnmanagedType::IUnknown)] Object^ pUnk,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::I2)] interior_ptr<short> groupingNumber
                    );

                    // 获取组个数
                    // DISPID dispID
                    // IUnknown * pUnk
                    // long * nGroupCnt
                    void GetGroupCount(
                        [InteropServices::In] System::Int32 dispID,
                        [InteropServices::In, InteropServices::MarshalAs(InteropServices::UnmanagedType::IUnknown)] Object^ pUnk,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::I8)] interior_ptr<long> nGroupCnt
                    );

                    // 获取元素字符串
                    // DISPID dispID
                    // IUnknown * pUnk
                    // OPMLPOLESTR __RPC_FAR * pCaStringsOut
                    // OPMDWORD __RPC_FAR * pCaCookiesOut
                    void GetElementStrings(
                        [InteropServices::In] System::Int32 dispID,
                        [InteropServices::In, InteropServices::MarshalAs(InteropServices::UnmanagedType::IUnknown)] Object pUnk,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::Struct)] interior_ptr<OPMLPOLESTR> pCaStringsOut,
                        [InteropServices::In, InteropServices::Out, InteropServices::MarshalAs(InteropServices::UnmanagedType::Struct)] interior_ptr<OPMDWORD> pCaCookiesOut
                    );

                };
                //typedef public struct  tagOPMLPOLESTR
                //{
                //    ULONG cElems;
                //    /* [size_is] */ LPOLESTR __RPC_FAR* pElems;
                //} OPMLPOLESTR;

                //typedef struct tagOPMLPOLESTR __RPC_FAR* LPOPMLPOLESTR;

                //typedef public struct  tagOPMDWORD
                //{
                //    ULONG cElems;
                //    /* [size_is] */ DWORD __RPC_FAR* pElems;
                //} OPMDWORD;

                //typedef struct tagOPMDWORD __RPC_FAR* LPOPMDWORD;
            }
        }
    }
}


    #region 自定义属性
    [
    Guid("EC0AB7F1-5D92-4FF1-96AE-7AC537C1347E"),
    ProgId("OPMNETSample.ExpanderProperty.1"),

    // No class interface is generated for this class and
    // no interface is marked as the default.
    // Users are expected to expose functionality through
    // interfaces that will be explicitly exposed by the object
    // This means the object can only expose interfaces we define

    ClassInterface(ClassInterfaceType.None),
    // Set the default COM interface that will be used for
    // Automation. Languages like: C#, C++ and VB allow to 
    //query for interface's we're interested in but Automation 
    // only aware languages like javascript do not allow to 
    // query interface(s) and create only the default one

    ComDefaultInterface(typeof(IDynamicProperty2)),
    ComVisible(true)
        ]
    public class ExpanderPropertyDemo : IDynamicProperty2, ICategorizeProperties, IOPMPropertyExpander2
    {
        private IDynamicPropertyNotify2 property_notify_ = null;
        private int m_numberOfVertices;
        private Point3d[] vertices;
        private int currrntIndex = 0; // Save the current vertex's index

        // 默认构造函数
        public ExpanderPropertyDemo()
        {
            m_numberOfVertices = 5;
            vertices = new Point3d[m_numberOfVertices];
            vertices[0] = new Point3d(1000, 1000, 0);
            vertices[1] = new Point3d(2000, 2000, 0);
            vertices[2] = new Point3d(3000, 3000, 0);
            vertices[3] = new Point3d(4000, 4000, 0);
            vertices[4] = new Point3d(5000, 5000, 0);

        }

        void IDynamicProperty2.Connect(object pSink)
        {
            property_notify_ = (IDynamicPropertyNotify2)pSink;
        }

        void IDynamicProperty2.Disconnect()
        {
            property_notify_ = null;
        }

        void ICategorizeProperties.GetCategoryName(int propcat, uint lcid, out string pbstrName)
        {
            pbstrName = "扩展属性";
        }

        void IDynamicProperty2.GetCurrentValueData(object pUnk, ref object varData)
        {
            varData = null;
        }

        void IDynamicProperty2.GetCurrentValueName(out string name)
        {
            name = null;
        }

        void IDynamicProperty2.GetCurrentValueType(out ushort pVarType)
        {
            pVarType = 12; // VT_VARIANT = 12
        }

        void IDynamicProperty2.GetDescription(out string description)
        {
            description = "扩展动态属性演示";
        }

        void IDynamicProperty2.GetDisplayName(out string name)
        {
            name = "当前顶点";
        }

        void IOPMPropertyExpander2.GetElementGrouping(int dispID, object pUnk, ref short groupingNumber)
        {
            groupingNumber = 3;
        }

        void IOPMPropertyExpander2.GetElementValue(int dispID, object pUnk, uint dwCookie, ref object pVarOut)
        {
            int index = (int)dwCookie / 3;
            int subIndex = ((int)dwCookie - index * 3) % 3;
            pVarOut = vertices[index][subIndex];
            currrntIndex = index;
        }

        void IOPMPropertyExpander2.GetGroupCount(int dispID, object pUnk, ref int nGroupCnt)
        {
            nGroupCnt = m_numberOfVertices;
        }

        void IDynamicProperty2.GetGUID(out Guid propGUID)
        {
            propGUID = new Guid("9CAF41C2-CA86-4ffb-B05A-AC43C424D076");
        }

        void IDynamicProperty2.IsPropertyEnabled(object pUnk, out int bEnabled)
        {
            bEnabled = 1;
        }

        void IDynamicProperty2.IsPropertyReadOnly(out int bReadonly)
        {
            bReadonly = 0;
        }

        void ICategorizeProperties.MapPropertyToCategory(int dispid, out int ppropcat)
        {
            ppropcat = 4;
        }

        void IDynamicProperty2.SetCurrentValueData(object pUnk, object varData)
        {
            /*
                         * when pick a point, this method is called.
                         */
            double[] xyz = (double[])varData;
            vertices[currrntIndex] = new Point3d(xyz[0], xyz[1], xyz[2]);
        }

        void IOPMPropertyExpander2.SetElementValue(int dispID, object pUnk, uint dwCookie, ref object VarIn)
        {
            int index = (int)dwCookie / 3;
            int subIndex = ((int)dwCookie - index * 3) % 3;
            Point3d point = vertices[index];
            if (subIndex == 0)
            {
                vertices[index] = new Point3d((double)VarIn, point.Y, point.Z);
            }
            else if (subIndex == 1)
            {
                vertices[index] = new Point3d(point.X, (double)VarIn, point.Z);
            }
            else if (subIndex == 2)
            {
                vertices[index] = new Point3d(point.X, point.Y, (double)VarIn);
            }
        }

/*        public unsafe void GetElementStrings(
            [In] int dispID,
            [In, MarshalAs(UnmanagedType.IUnknown)] object pUnk,
            [In, Out, MarshalAs(UnmanagedType.Struct)] ref OPMLPOLESTR pCaStringsOut,
            [In, Out, MarshalAs(UnmanagedType.Struct)] ref OPMDWORD pCaCookiesOut)
        {
            List<string> strings = new List<string> { "顶点 X 坐标", "顶点 Y 坐标", "顶点 Z 坐标" };
            List<uint> values = new List<uint> { 0, 1, 2 };
            pCaStringsOut = OPMUtils.CreateOPMLPOLESTR(strings);
            pCaCookiesOut = OPMUtils.CreateOPMDWORD(values);
        }*/

        public void Initialize()
        {
            ExpanderPropertyDemo epd = new ExpanderPropertyDemo();
        }

        public void Terminate()
        {
            throw new NotImplementedException();
        }
    }
    #endregion
运行结果及报错内容

一种结果是显示不支持语法,
另一种结果是实现接口后,还是出现错误

我的解答思路和尝试过的方法

C#调用C++的结构体,以接口类的形式调用
尝试过网络一些C#调用C++的结构体方式,显示还是报错,导入C++结构体,是后面再指向C++的结构体,而接口实现,则是开始就指向C++的结构体

我想要达到的结果

希望能有一个好的解决方案,能让代码通过测试

  • 写回答

2条回答 默认 最新

  • 来灵 2022-08-19 14:44
    关注

    C++ dll接口定义,举个例子

    struct User
    {
        char userId[64];
        char username[32];
        char password[64];
    };
    
    DLL_EXPORT int STDCALL API_UpdateOneUser
    (
        IN User *user
    );
    

    C#数据结构及接口定义

    [StructLayout(LayoutKind.Sequential)]
    public struct User
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
            public char[] userId;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] username;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
            public char[] password;
        }
    
    const string DLL_PATH = "mydll.dll";
    
    [DllImport(DLL_PATH, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    static extern int API_UpdateOneUser(ref User user);
    
    //以下是接口调用
    User user = new User();
    user.userId = ...
    user.username = ...
    int result = API_UpdateOneUser(ref user);
    
    
    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月19日
  • 赞助了问题酬金50元 8月19日
  • 修改了问题 8月19日
  • 创建了问题 8月19日

悬赏问题

  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误