代码之家  ›  专栏  ›  技术社区  ›  tzup

如何从C++向C语言传递一个常数无符号字符

  •  3
  • tzup  · 技术社区  · 14 年前

    因此,我在非托管C++中有一个函数,当某些文本恰好“到达”时调用它。

    #using <MyParser.dll>
    ...
    void dump_body(const unsigned char *Body, int BodyLen) 
    {
      // Need to pass the body to DumpBody, but as what type?
         ...
      MyParser::Parser::DumpBody(???);
    }
    

    垃圾桶 C dll中是否定义了静态函数,该函数应采用一个类型的参数?

    身体 保存长度为的字符(文本)数组 博迪恩 .

    显然这里有一些编组工作要做,但我不知道怎么做。

    请帮忙。

    3 回复  |  直到 14 年前
        1
  •  2
  •   plinth    14 年前
    void dump_body(const unsigned char *body, int bodyLen)
    {
        // you might want a different encoding...
        String ^str = gcnew String((sbyte*)body, 0, bodyLen, gcnew ASCIIEncoding);
        MyParser::Parser::DumpBody(str);
    }
    

    dumpbody需要一个字符串。

        2
  •  2
  •   Danvil    14 年前

    FLULFEN代码描述托管C代码与非托管C/C++ DLL之间通过PInvoke进行通信的情况。其基本思想是,您可以将C代码传递给一个C委托。这个 const unsigned char* 转换为 string 具有 Marshal.PtrToStringAnsi .

    C++:

    typedef void FncFoo (const char*);
    
    FncFoo callback = 0;    
    
    extern "C" {
      // this function is called from C# to pass the delegate
      void TakeFooCallback(FncFoo f) {
        callback = f;
      }
    }
    
    // C function calling C#
    void dump_body(const unsigned char *Body, int BodyLen) {
      if(callback) {
        callback(Body);
      }
    }
    

    C:

    class StringC2CS {
    
      delegate void DlgFoo(IntPtr a);
    
      [DllImport("myclib.dll")] // name of the dll
      void TakeFooCallback(DlgFoo callback);
    
      // this function gets called by C
      void FooImpl(IntPtr a) {
        string str = Marshal.PtrToStringAnsi(a);
        // use string
      }
    
      public StringC2CS() {
        // passes a callback to C
        TakeFooCallback(new DlgFoo(FooImpl));
      }
    }
    
        3
  •  0
  •   Community holdenweb    7 年前

    我最后用 Danvil 的方法。我在C++的DLL中封装了C代码,然后我做了另一个引用C++ DLL的C*yDLL,并公开了我想要的托管代码中的功能。所以这里是:

    C++ DLL:

    h文件

     // Definition of a callback function to be called when some data arrives
     typedef void (*FncDlg) (const unsigned char*, int len);
    
     // Declaration of the function that will be exposed in managed code. 
     // The managed code will use this function to pass in a delegate
     extern "C" __declspec(dllexport) void AttachCallback(FncDlg f);
    
     // Declaration of a function that receives data and passes it to managed code
     void PassData(const unsigned char *Body, int BodyLen);
    

    .CPP文件

     // Instantiate a global function pointer to nothing
     void (*callback)(const unsigned char*, int len) = 0; 
    
     // This is called by C# to pass in a delegate
     void AttachCallback(FncDlg f) 
     {
        // Save delegate globally (to be triggered later when we receive data)
        callback = f;
     }
    
     // This is the function called when data is read from the socket
     void PassData(const unsigned char *Body, int BodyLen)
     {
        if(callback) {
        callback(Body, BodyLen);
        }
     }
    

    C·dll:

     public static class Parser
     {
        public delegate void DlgDumpTipData(IntPtr a, int len);
    
        [DllImport("C++ dll name here", EntryPoint = "AttachCallback", ExactSpelling = true)]
        public static extern void AttachCallback(DlgDumpTipData callback); 
    
        public static int ConnectAndStartReceive(...)
        {
           // Attach a callback function (called when a message is received from data feed)
           AttachCallback(DumpDataCalback);
           ...
        }
    
        public delegate void MsgHandler(string msg);
        // When data arrives from the C library, this event passes it on to C# clients 
        public static event MsgHandler OnMessageArrived = delegate { };
    
        public static void DumpDataCalback(IntPtr ptr, int len)
        {
           //string str = Marshal.PtrToStringAnsi(ptr); 
           string dumpData;
           sbyte[] byteArr = new sbyte[len];
           for (int i = 0; i < len; i++)
           {
              // WARNING: if byte > 127 we have a problem when casting from Byte to SByte
              // In this case there is no problem, tested with values over 127 and it
              // converts fine to Latin-1 using the String overload 
              byteArr[i] = (sbyte)Marshal.ReadByte(ptr, i); 
           }
    
           unsafe
           {
             fixed (sbyte* pbyteArr = byteArr) // Instruct the GC not to move the memory
             {
                 dumpData = new String(pbyteArr, 0, len, Encoding.GetEncoding("ISO-8859-1"));
             }
           }
    
           // Send data to whoever subscribes to it
           OnMessageArrived(dumpData);
           GC.Collect(); // This slows things down but keeps the memory usage low
        }        
     }