<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d6566853\x26blogName\x3d1%25+inspiration\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttps://patke.blogspot.com/search\x26blogLocale\x3den\x26v\x3d2\x26homepageUrl\x3dhttp://patke.blogspot.com/\x26vt\x3d2795022480681574377', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Wednesday, July 28, 2004

The other day I wrote a quick posts about passing a string array from C++ to a C# program on Pocket PC.  So today I thought I would go over a bit of code showing the opposite.  How to get a string[] into C++ from managed C#.

Sounds complicated, but the process is actually quite simple.  First create a struct in C++ which contains a wide character pointer.  Then create the struct in C# - the trick here is to use unmanaged code in C# to create the char pointer.  From there, the rest is easy.  Just pass an array of the struct type into the C++ program.

Something like this:

typedef struct _STR
   WCHAR* command;
} STR;

public unsafe struct CMD
   public char* command;
   public CMD(char* cmd)
      command = cmd;

Looks good you say, but doesn't quite work because C# doesn't support character pointers.  ...but notice the "unsafe" key word - that is where the magic is.

So to generate our array of pointers, we have code like...

internal class PInvokeStringArray
   private string[] ary = {" ", " ", " ", " ", " "}; //length = 5 - initialized with default values.
   public int Length = 0;
   public string[] getArray()
      return ary;
   public PInvokeStringArray(string[] array)
      if(array==null) return; //use the defaults.
      Length = array.Length;
      if(Length > 5)
         throw new ArgumentException("Unable to perform the operation " + 
            "requested because too many directory commands were specified. " +
            "This program can only accept a maximum of 5 directory commands.");
      for(int i=0;i Length;i++)    
         ary[i] = array[i] + "\0";

PInvokeStringArray psa = new PInvokeStringArray(cmdsStr);
cmdsStr = psa.getArray();
CMD[] cmds = new CMD[5];
   fixed(char* temp1 = cmdsStr[0].ToCharArray(), 
      temp2 = cmdsStr[1].ToCharArray(), 
      temp3 = cmdsStr[2].ToCharArray(), 
      temp4 = cmdsStr[3].ToCharArray(),
      temp5 = cmdsStr[4].ToCharArray())
   cmds[0] = new CMD(temp1);
   cmds[1] = new CMD(temp2);
   cmds[2] = new CMD(temp3);
   cmds[3] = new CMD(temp4);
   cmds[4] = new CMD(temp5);

Anyone looking at this code for more then two seconds can see the obvious downside.  The array passed into C++ must be of a limited size.  Because of the nature of the "fixed" command, I couldn't see a way around this, but would really appreciate any suggestions.  ...but at any rate, it works for me.

Comments: Post a Comment