不对外是什么意思,可以访问public的方法,受保护的不行

解决方案 »

  1.   

    c#调用c++dll 一般情况下能遇到的问题大概是一下两点
    1. 数据类型转换问题 
    2. 指针或地址参数传送问题 
    你问的问题是什么意思,不太明白
      

  2.   

    举例 :
    dll  对外发布唯一接口类似于    void   Get(IInterface ** ppInter);   IInterface是抽象接口,继承 IUnknown,dll 内部有类继承自IInterface,并实现了功能。
    问题  : c#如何获取ppInter? 如何访问IInterface声明的成员函数?(声明了哪些函数外部是知道的)
      

  3.   


    麻烦给点伪代码示例下.
    [c++]
    Interface test1
    {
         void a();
         void b(char*a);
    };Interface test
    {
         void GetTest1(test1**pptest);
         void b(char*a);
    };dll 对外发布唯一接口:
      void Get(test** a);请问c#部分如何实现,给点伪代码展示下如何访问 test1 的 a()函数, 谢谢了!
      

  4.   

    给你一个样例。
    C++ 接口
    struct ICForCS2
    {
    virtual int Login(const char* user_name, const char* password, int login_type, LoginInfo *plogin_info, const char* end_point_url, const char* local_ip = NULL) = 0;
    virtual int GetUdiskInfo2(s_udiskinfo *a, int max) = 0;
    };C++ 的获取接口的 API。
    CFORCS_API void GetICForCS2(ICForCS2 **p);C# 定义对应的接口
    [StructLayout(LayoutKind.Sequential)]
    struct INativeCSForC2
    {
    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    public delegate int _LoginHandler(IntPtr @this, [In, MarshalAs(UnmanagedType.LPStr)] string user_name, [In, MarshalAs(UnmanagedType.LPStr)] string password, [In, MarshalAs(UnmanagedType.I4)]int login_type, [In, Out] ref LoginInfo plogin_info, [In, MarshalAs(UnmanagedType.LPStr)] string end_point_url, [In, MarshalAs(UnmanagedType.LPStr)] string local_ip);
    public _LoginHandler Login; [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    public delegate int _GetUdiskInfoHandler([In] IntPtr @this, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] s_udiskinfo[] info, int max);
    public _GetUdiskInfoHandler GetUdiskInfo;
    }C# 定义这个接口。
    interface ICSForC22
    {
    int Login([In, MarshalAs(UnmanagedType.LPStr)] string user_name, [In, MarshalAs(UnmanagedType.LPStr)] string password, [In, MarshalAs(UnmanagedType.I4)]int login_type, [In, Out] ref LoginInfo plogin_info, [In, MarshalAs(UnmanagedType.LPStr)] string end_point_url, [In, MarshalAs(UnmanagedType.LPStr)] string local_ip);
    int GetUdiskInfo(s_udiskinfo[] info);
    }
    添加一个包装类。
    class NativeCSForC2 : ICSForC22
    {
    public NativeVTable<INativeCSForC2> _native;
    int ICSForC22.Login(string user_name, string password, int login_type, ref LoginInfo login_info, string end_point_url, string local_ip)
    {
    return _native._nativeInterface.Login(_native._ptrInterface, user_name, password, login_type, ref login_info, end_point_url, local_ip);
    } int ICSForC22.GetUdiskInfo(s_udiskinfo[] info)
    {
    return _native._nativeInterface.GetUdiskInfo(_native._ptrInterface, info, info.Length);
    } }C# 定义 API 函数对应的方法。

    [DllImport(....)]
    private static extern void _GetICForCS2([Out] out IntPtr ptrInterface);
    public static NativeCSForC2 GetICForCS2()
    {
    IntPtr ptrInterface;
    _GetICForCS2(out ptrInterface);
    return new NativeCSForC2
    {
    _native = new NativeVTable<INativeCSForC2>(ptrInterface),
    };
    }
    如果使用很多的话,定义一个 模板包装
    class NativeVTable< I > : IDisposable
    {
    public IntPtr _ptrInterface;
    public I _nativeInterface;
    private Action< IntPtr > _release = null;
    public NativeVTable(IntPtr ptrInterface)
    {
    System.Diagnostics.Debug.Assert(ptrInterface != IntPtr.Zero);
    _ptrInterface = ptrInterface;
    _nativeInterface = (I)Marshal.PtrToStructure(Marshal.ReadIntPtr(ptrInterface, 0), typeof(I));
    }
    public NativeVTable(IntPtr ptrInterface, Action< IntPtr > release) : this(ptrInterface)
    {
    _release = release;
    }
    public void Dispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    } private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
    if (!this.disposed)
    {
    if (_release != null)
    {
    _release(_ptrInterface);
    }
    disposed = true;
    }
    } ~NativeVTable()
    {
    Dispose(false);
    } }最后使用:
    var vv = (ICSForC22)NativeImport.GetICForCS2();
      

  5.   

    简单说,就是顶一个和 C 虚表一致的  [StructLayout(LayoutKind.Sequential)] 特性的接口。
    这样,就可以把虚表中的方法转换到 托管内存中。在定义个C# 的类来包装这个,并暴露一个一致的、C#模式的接口。(如果内部使用,就可以不要包装,直接调用)。在使用的时候,使用 C 提供的 API 来获取接口,解析这个接口,获取虚表。 p->lpVtbl 就是虚表的位置。
    在 C# 中,她其实就是其 0 偏移的引用。
    实现 C# 接口,就是找到该方法对应的 虚表中的方法委托,然后呼叫之。如果是 IUnknown 接口,需要自己实现更加复杂的 IUnknown 的三个方法。我记得好像不久前,也有人问,怎么处理一个接口的问题。你可以看看。
      

  6.   


    非常感谢你,一般的interface用你的方法是可以,还有两点请教下:
    1)virtual int  _stdcall  Login()--------------会出错;
    2)Iunknow 3个方法我是定义在NativeVTable里还是interface ICSForC22里。
    盼回复。
      

  7.   

    这个应该没法实现吧用CLI封装C++,然后暴露托管接口,这样是不是好点。
      

  8.   

    可以实现的,现在就是Iunknown的三个方法不太好搞。
      

  9.   


    ((Action)Marshal.GetDelegateForFunctionPointer((IntPtr)(**(int**)a), typeof(Action)))();
      

  10.   

    __thiscall 
    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    __stdcall
    [UnmanagedFunctionPointer(CallingConvention.StdCall)] //或者删除这句,因为缺省就是 StdCall。
    //而 C 语言的导出函数呼叫约定缺省也应该是 __stdcall 。我是看你的代码里面没有 __stdcall 约定才明确写上的,在C/C++ 里面定义导出最好使用 __stdcall.
    这样在 C# 里面就是缺省的呼叫约定了。
    至于 IUnknown 不需要在 C# 里面导出,因为 C# 的 AddRef 和 Release 是由GC 决定的。
    你需要自己处理,使用 IDisposed 接口。
    至于 QI 在 C# 里面是不存在的,她对应于类型转换。
    当你需要 QI 除 IUnknown 之外的接口,你都需要有对应的C# 接口,然后,就可以he 样例中 API 一样,QI 到指定的接口,然后转换为对应的 C# 的接口实例。当你的接口继承 IUnknwon 时,需要注意 INativeCSForC2 接口布局,有三个 IUnknown 的接口方法委托在前面。
      

  11.   


    谢谢 Saleayas 的细心回答,在你的指导下  c#里调用c++的接口貌似功能函数方面可以调用了 ,引用计数的问题,后面我再 研究研究。现在有个新的问题 ,例如:【c++】
      声明接口,不实现:
       ITest :IUnknown
    {
           void SetInfo(void** pInfo);
    }IBase
    {
         void   SetITest(ITest*   pITest);
    }[c#]
    需要实现ITest, 我该如何定义呢?
      

  12.   

    [c#实现代码如下:][StructLayout(LayoutKind.Sequential)]
        public class ITest
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate int QueryInterfaceHandler(ref Guid riid, out IntPtr ppvObject);
        public QueryInterfaceHandler QueryInterface = new QueryInterfaceHandler(QueryInterfaceFunc);    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate uint AddRefHandler(IntPtr @this);
        public AddRefHandler AddRef ;    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate uint ReleaseHandler(IntPtr @this);
        public ReleaseHandler Release;    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate void SetInfoHandler(ref IntPtr pInfo);
        public SetInfoHandler SetInfo= newSetInfoHandler(SetInfoFunc);
    第一次传入c++是可以调用到addref/Release等函数,出来后,再调用发现对应的vtable都是野指针看着像是释放了。
    求高人指点?