• <tfoot id='E1gk2'></tfoot>

    <small id='E1gk2'></small><noframes id='E1gk2'>

  • <i id='E1gk2'><tr id='E1gk2'><dt id='E1gk2'><q id='E1gk2'><span id='E1gk2'><b id='E1gk2'><form id='E1gk2'><ins id='E1gk2'></ins><ul id='E1gk2'></ul><sub id='E1gk2'></sub></form><legend id='E1gk2'></legend><bdo id='E1gk2'><pre id='E1gk2'><center id='E1gk2'></center></pre></bdo></b><th id='E1gk2'></th></span></q></dt></tr></i><div id='E1gk2'><tfoot id='E1gk2'></tfoot><dl id='E1gk2'><fieldset id='E1gk2'></fieldset></dl></div>

    <legend id='E1gk2'><style id='E1gk2'><dir id='E1gk2'><q id='E1gk2'></q></dir></style></legend>
        <bdo id='E1gk2'></bdo><ul id='E1gk2'></ul>
      1. 将 IUnknowns 的 SAFEARRAY 转换/转换为接口指针的可迭代数组

        Convert/cast SAFEARRAY of IUnknowns to an iterable array of interface pointers(将 IUnknowns 的 SAFEARRAY 转换/转换为接口指针的可迭代数组)
          1. <legend id='ojjLc'><style id='ojjLc'><dir id='ojjLc'><q id='ojjLc'></q></dir></style></legend>

              <tbody id='ojjLc'></tbody>

            <i id='ojjLc'><tr id='ojjLc'><dt id='ojjLc'><q id='ojjLc'><span id='ojjLc'><b id='ojjLc'><form id='ojjLc'><ins id='ojjLc'></ins><ul id='ojjLc'></ul><sub id='ojjLc'></sub></form><legend id='ojjLc'></legend><bdo id='ojjLc'><pre id='ojjLc'><center id='ojjLc'></center></pre></bdo></b><th id='ojjLc'></th></span></q></dt></tr></i><div id='ojjLc'><tfoot id='ojjLc'></tfoot><dl id='ojjLc'><fieldset id='ojjLc'></fieldset></dl></div>

                <bdo id='ojjLc'></bdo><ul id='ojjLc'></ul>

              • <tfoot id='ojjLc'></tfoot>
                • <small id='ojjLc'></small><noframes id='ojjLc'>

                • 本文介绍了将 IUnknowns 的 SAFEARRAY 转换/转换为接口指针的可迭代数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我在 C# 中有以下接口,其中一个具有相同名称(没有我)的类实现它.

                  I have the following interface in C# with a class with a same name (without I) implementing it.

                  [ComVisible(true)]
                  [Guid("B2B134CC-70A6-43CD-9E1E-B3A3D9992C3E")]
                  public interface IOrder
                  {
                      long GetQuantity();
                      long GetOrderType();
                      long GetPositionType();
                  }
                  

                  公共类 Order 的实现:IOrder 只是三个私有字段和一个需要 3 个参数的构造函数.

                  The implementation of the public class Order : IOrder is just three private fields and a constructor with required 3 parameters.

                  在其他地方,我有以下方法,其结果是我想在 C++ 非托管代码中工作,通过 COM 和 .tlb/.tlh 文件传输到那里.

                  Somewhere else, I have the following method with a result with which I want to work inside a C++ unmanaged code, transferred there via COM and .tlb/.tlh files.

                  public ScOrder[] GetOrders()
                  {
                      //constant return value for simplicity
                      return new Order[] {    
                          new Order(1, 2, 3),
                          new Order(4, 5, 6)
                      };
                  }
                  

                  我已经设法在使用 C# 托管代码的 C++ 非托管代码之间进行基础工作.

                  I've already managed to get the basics work between the C++ unmanaged code using the C# managed code.

                  但是类数组被证明是一个不同的挑战......

                  But class arrays proved to be a different challange...

                  我承认,对我来说,COM 是新的,令人困惑,C++ 早已被遗忘......,但我正在开发这两个库,所以我不会放弃;我希望 C++ DLL 在某些程序和我的 C# 代码之间充当代理.

                  I admit that for me, the COM is new and brutally confusing and C++ long forgotten ... , but I'm developing both libraries so I'm not giving up; I want the C++ DLL to work as a proxy between some program and my C# code.

                  澄清:我既没有使用 MFC,也没有使用 ATL.我在 C++ 代码中使用 #import 来获取 C# 生成的接口和类指针以及其他我不太了解的 COM 内容.

                  Clarification: I'm using neither MFC nor ATL. I use #import in the C++ code for getting the C# generated interface and class pointers and other COM stuff I don't quite understand yet.

                  经过一个小时的研究,我只是去这里寻求帮助>.<

                  After hour of researching, I'm just going here and beg for help >.<

                  以下是我想要实现的 C++ 代码.

                  The following is the C++ code of what I'm trying to achieve.

                  //this is how the instance of C# gets created, read it from the internets
                  //this type has the method GetOrders
                  IProxyPtr iPtr;
                  CoInitialize(NULL);
                  iPtr.CreateInstance(CLSID_Proxy);
                  
                  IOrderPtr* ordArr; 
                  //IOrderPtr is just a pointer to the interface type transferred
                  //right? So IOrderPtr* should represent the array of those pointers, right? 
                  
                  SAFEARRAY* orders;
                  iPtr->GetOrders(&orders);
                  

                  现在,我需要一些我还不明白的 COM 魔法来将 SAFEARRAY* 转换为 IOrderPtr* 或其他东西,这样我就可以遍历返回的整个数组并调用Order"类型的方法

                  Now at this point, I need some COM magic I don't yet understand to convert that SAFEARRAY* to IOrderPtr* or something so I can iterate over the whole array returned and call the methods of the type "Order"

                  • GetQuantity()
                  • GetOrderType()
                  • GetPositionType()

                  所以对于第一个周期,我将获得值 1、2、3,对于第二个周期,我将获得值 4、5、6.

                  So for the first cycle, I'll get values 1,2,3 and for the second cycle, I'll get values 4,5,6.

                  由于我是 C++ 和 C# 库的作者,我可以跳过所有这些 COM 疯狂的东西,并创建方法来获取集合计数和其他方法来获取特定索引上的属性值.

                  Since I'm the author of both C++ and C# library, I can just skip all of this COM crazy stuff and make methods to get the collection count and other methods to get the value of property on certain index.

                  但这似乎不太好.我怀疑我想要的机制很简单,但我在谷歌上找到的所有答案总是缺少一些东西.

                  But that just doesn't seem nice. I suspect the mechanics of what I want are easy but all the answers I found on google are always missing something.

                  推荐答案

                  不知道你在 C++ 客户端中是使用 MFC、ATL 还是其他一些库,很难简化,所以我将使用 Win32 API(这些库提供用于更简单地使用安全数组的辅助类)

                  Without knowing whether you use MFC, ATL or some other library in your C++ client, it is hard to simplify it so I will use Win32 API (these libraries provide helper classes for simpler usage of safearrays)

                  但是,我假设您通过 Interop 类型库的 #import 使用 C# lib,因此您可以使用生成的智能指针类.我还将假设您返回 IUnknowns 的 SAFEARRAY 而不是包含 IUnknowns 的变体的 SAFEARRAY - 这可以通过在 C# 接口上指定适当的编组属性来修改,例如:

                  However, I will assume that you use you C# lib through #import of Interop type library, so you can use generated smart pointer classes. I will also assume that you return a SAFEARRAY of IUnknowns and not a SAFEARRAY of Variants which contain IUnknowns - this can be modified by specifying appropriate marshaling attributes on you C# interface, e.g:

                  [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] 
                  // [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
                  IOrder[] GetOrders();
                  

                  以下是 C# 类型的实现(答案底部有示例解决方案的链接):

                  Here are the implementations of C# types (link to a sample solution is at the bottom of the answer):

                  [ComVisible(true)]
                  [Guid("F3071EE2-84C9-4347-A5FC-E72736FC441F")]
                  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
                  public interface IProxy
                  {
                      [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] 
                      IOrder[] GetOrders();
                  }
                  
                  [ComVisible(true)]
                  [Guid("8B6EDB6B-2CF0-4eba-A756-B6E92A71A48B")]
                  [ClassInterface(ClassInterfaceType.None)]
                  public class Proxy : IProxy
                  {
                      public IOrder[] GetOrders() { return new[] {new Order(3), new Order(4)};        }
                  }
                  
                  [ComVisible(true)]
                  [Guid("CCFF9FE7-79E7-463c-B5CA-B1A497843333")]
                  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
                  public interface IOrder
                  {
                      long GetQuantity();
                  }
                  
                  [ComVisible(true)]
                  [Guid("B0E866EB-AF6D-432c-9560-AFE7D171B0CE")]
                  [ClassInterface(ClassInterfaceType.None)]
                  public class Order : IOrder
                  {
                      private int m_quantity;
                      public Order(int quantity) { m_quantity = quantity; }
                      public long GetQuantity() { return m_quantity; }
                  }
                  

                  必须使用 Regasm 构建和注册服务器.为简单起见,我将执行 regasm/codebase/tlb $path 以避免在 GAC 中签名和注册.

                  The server must be built and registered with Regasm. For simplicity, I will do regasm /codebase /tlb $path to avoid signing and registering in GAC.

                  客户端代码应该是这样的:

                  The client code should like something like this:

                  #import "Server.tlb" no_namespace // you should use namespaces! this is a demo
                  
                  int _tmain(int argc, _TCHAR* argv[])
                  {
                    CoInitialize(NULL);      // init COM
                  
                    IProxyPtr proxy(__uuidof(Proxy));         // instantiate the proxy
                    SAFEARRAY* orders = proxy->GetOrders();   // to return orders
                  
                    LPUNKNOWN* punks;   
                    HRESULT hr = SafeArrayAccessData(orders, (void**)&punks); // direct access to SA memory
                    if (SUCCEEDED(hr))
                    {
                      long lLBound, lUBound;  // get array bounds
                      SafeArrayGetLBound(orders, 1 , &lLBound);
                      SafeArrayGetUBound(orders, 1, &lUBound);
                  
                      long cElements = lUBound - lLBound + 1; 
                      for (int i = 0; i < cElements; ++i)  // iterate through returned objects
                      {                              
                        LPUNKNOWN punk = punks[i];     // for VARIANTs: punk = punks[i].punkVal
                        IOrderPtr order(punk);         // access the object via IOrder interface
                        long q = order->GetQuantity(); // and voila!
                        std::cout << "order " << i + 1 << ": Quantity " << q << std::endl;
                      }       
                      SafeArrayUnaccessData(orders);
                    }
                    SafeArrayDestroy(orders);
                    return 0;
                  }
                  

                  示例项目可以在这里找到.请注意,您必须在第一次构建时手动注册 .tlb,项目不会这样做,但您可以根据需要添加构建后步骤

                  The sample project can be found here. Please note that you must manually register the .tlb first time you build it, the project doesn't do it, but you can add a post-build step if you want

                  这篇关于将 IUnknowns 的 SAFEARRAY 转换/转换为接口指针的可迭代数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  Performance overhead of using attributes in .NET(在 .NET 中使用属性的性能开销)
                  Accessing attribute info from DTE(从 DTE 访问属性信息)
                  c# Hide a property in datagridview with datasource(c#使用数据源隐藏datagridview中的属性)
                  Extract Display name and description Attribute from within a HTML helper(从 HTML 帮助器中提取显示名称和描述属性)
                  C# Attributes and their uses(C# 属性及其用途)
                  C# - Getting all enums value by attribute(C# - 按属性获取所有枚举值)

                    <legend id='G4k5v'><style id='G4k5v'><dir id='G4k5v'><q id='G4k5v'></q></dir></style></legend>

                        • <bdo id='G4k5v'></bdo><ul id='G4k5v'></ul>
                          <tfoot id='G4k5v'></tfoot>

                          <small id='G4k5v'></small><noframes id='G4k5v'>

                            <tbody id='G4k5v'></tbody>
                          <i id='G4k5v'><tr id='G4k5v'><dt id='G4k5v'><q id='G4k5v'><span id='G4k5v'><b id='G4k5v'><form id='G4k5v'><ins id='G4k5v'></ins><ul id='G4k5v'></ul><sub id='G4k5v'></sub></form><legend id='G4k5v'></legend><bdo id='G4k5v'><pre id='G4k5v'><center id='G4k5v'></center></pre></bdo></b><th id='G4k5v'></th></span></q></dt></tr></i><div id='G4k5v'><tfoot id='G4k5v'></tfoot><dl id='G4k5v'><fieldset id='G4k5v'></fieldset></dl></div>