title: Converting C function to C#
body: <p>I'm looking for some guidance on whether converting this function from C to C# is possible.</p>
  
  <p>The function is:</p>
  
  <pre><code>int parseClientPacket(byte * packet_data, u32 packet_size, int is_start_of_packet, u32 header_size, u32 num_to_parse, const u16 * type_map, const u16 * size_map, ...)
  {
      const u32   common_size_map[]   = { 0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x04, 0x0C, 0x40, 0x08, 0x00, 0x06, 0x02 };
      byte        *data               = 0;
      u32         pflag               = 0;
      u32         flag                = 1U &lt;&lt; 0;;
      u32         num_parsed          = 0;
      int         ret                 = 0;
      va_list     args;
  
      va_start(args, size_map);
  
      if (header_size == 0)
      {
          goto done;
      }
  
      if (is_start_of_packet == 0)
      {
          data = packet_data + header_size + 2;
  
          if (header_size &gt;= 4)
          {
              pflag = *(u32*)(packet_data + 2);
          }
          else if (header_size &gt;= 3)
          {
          }
          else if (header_size == 2)
          {
              pflag = *(u16*)(packet_data + 2);
          }
          else
          {
              pflag = packet_data[2];
          }
      }
      else
      {
          data = packet_data + header_size + 9;
  
          if (header_size &gt;= 4)
          {
              pflag = *(u32*)(packet_data + 9);
          }
          else if (header_size &gt;= 3)
          {
          }
          else if (header_size &gt;= 2)
          {
              pflag = *(u16*)(packet_data + 9);
          }
          else
          {
              pflag = packet_data[9];
          }
      }
  
      if (num_to_parse == 0)
      {
          return 1;
      }
  
      for (u32 i = 0; i &lt; num_to_parse; i++, flag &lt;&lt;= 1)
      {
          void    **arg = va_arg(args, void**);
          u16     size;
  
          if (pflag &amp; flag)
          {
              if (is_start_of_packet &amp;&amp; data &gt; packet_data + packet_size)
              {
                  return 0;
              }
  
              if (type_map[i] == 0x0C)
              {
                  if (size_map[i] &lt;= 1)
                  {
                      size = *(u16*)data;
  
                      if (arg)
                      {
                          *arg = (void*)data;
                      }
                      data = data + size + 2;
                  }
                  else
                  {
                      byte num_blocks = *data++;
                      size            = 0;
  
                      for (u32 i = 0; i &lt; num_blocks; i++, data = data + size + 2)
                      {
                          size = *(u16*)data;
  
                          if (arg)
                          {
                              *arg = (void*)data;
                          }
                      }
                  }
              }
              else if (type_map[i] == 0x0D)
              {
                  u32 *arg_sz = va_arg(args, u32*);
                  size        = *(u16*)data;
  
                  if (arg)
                  {
                      *arg = (void*)(data + 2);
                  }
                  if (arg_sz)
                  {
                      *arg_sz = size;
                  }
                  data    = data + size + 2;
  
                  if (is_start_of_packet &amp;&amp; data &gt; packet_data + packet_size)
                  {
                      return 0;
                  }
              }
              else if (type_map[i])
              {
                  u16 size = common_size_map[type_map[i]] * size_map[i];
  
                  if (is_start_of_packet &amp;&amp; data + size &gt; packet_data + packet_size)
                  {
                      return 0;
                  }
  
                  if (arg)
                  {
                      mg_memcpy((void*)arg, data, size);
                  }
                  data = data + size;
              }
              else
              {
                  if (arg)
                  {
                      *arg = (void*)data;
                  }
                  data = data + (common_size_map[type_map[i]] * size_map[i]);
  
                  if (is_start_of_packet &amp;&amp; data &gt; packet_data + packet_size)
                  {
                      goto done;
                  }
              }
          }
          else if (type_map[i] == 0x0C)
          {
              if (arg)
              {
                  *arg = 0;
              }
          }
          else if (type_map[i] == 0x0D)
          {
              va_arg(args, u32*);
          }
      }
      ret = 1;
  
  done:
      va_end(args);
      return ret;
  }
  </code></pre>
  
  <p>The function arguments are quite clear to me in C, and earlier today I was trying to make this function in C#.</p>
  
  <p>However due to some limitations of C#'s <code>unsafe</code> code I wasn't able to completely finish it.</p>
  
  <p>I was stuck at the last parameter(s), which was the variable number of arguments. I have no clue how to write this one.</p>
  
  <p>When you pass something to the va_list, it takes a bunch of pointers to unknown-type data, like so:</p>
  
  <pre><code>byte        action          = 0xFF;
  byte        *npc_block      = 0;
  u32         character_id;
  u32         skill_id;
  u32         skill_tid;
  byte        arg_5;
  byte        arg_6;
  byte        arg_7;
  u32         npc_tid;
  u32         npc_function;
  Npc         *npc;
  
  parseClientPacket(p-&gt;data, p-&gt;size, 1, 1, 8, type_map, size_map,
          &amp;action,
          &amp;npc_block,
          &amp;character_id,
          &amp;skill_id,
          &amp;skill_tid,
          &amp;arg_5,
          &amp;arg_6,
          &amp;arg_7)
  </code></pre>
  
  <p>I have tried passing replacing the variable amount of arguments with a <code>params object[]</code>, however <code>byte*</code> do not seem to be castable to <code>object</code> 's.</p>
  
  <p>Thanks!</p>