0

I'm trying to get a pointer to a string, where the pointer is of type int. I'm not sure if I'm doing it correctly. I just found out yesterday about unsafe and fixed, so I'm still questioning this a bit. Can I just cast the char* to int? I'm not getting any errors, but the methods are not working, so I'm not sure if the pointer is wrong or if I'm doing something wrong with the 3rd party OCX (for which there's no support).

3rd Party Documentation for C++ calls:

BlobToVariant(VARIANT *pV, long BlobPointer)
WriteVToFile(VARIANT *pV)

What VS2010 C# Intellisense says:

BlobToVariant(ref object v, int BlobPointer)
WriteVToFile(ref object v)

Here is my code:

string imageBlob = "superlongstring";

// 3rd Party ActiveX control for tiff image files
TIFFLib.TIFF tiff = new TIFFLib.TIFF();

// Variant object that will hold image
object blobVariant = new object();

unsafe
{
    fixed (char* p = imageBlob)
    {
        int blobPointer = (int)p;

        tiff.BlobToVariant(ref blobVariant, blobPointer);
        tiff.WriteVToFile(ref blobVariant);
    }
}
DanM7
  • 2,203
  • 3
  • 28
  • 46
  • 1
    If this method expects a pointer to a C-style ASCII/UTF-8 string, then no, this will not work; C# chars are 16 bits wide. You'll probably want to use one of the `Encoding` classes to convert the string to a `byte[]` first, then get a `byte*` from that. – cdhowie Oct 17 '12 at 18:03
  • Frequently a `StringBuilder` can be used as a string pointer (at least in cases of pinvoke-ing); without know more about `tiff`, maybe give that a try? – Brad Christie Oct 17 '12 at 18:03
  • 1
    @BradChristie It looks like the method signature accepts `int` -- which would be a serious issue if this application is ever run on a 64-bit host... – cdhowie Oct 17 '12 at 18:04
  • You cannot cast a pointer to a char ( which is an address ) to an integer. It would make no sense to do so. Its not clear what you are trying to do. Post the documentation on `BlobToVariant` and `WriteVToFile` if you want help. – Security Hound Oct 17 '12 at 18:05
  • Dan, do you have any documentation for this method that you could link us to? – cdhowie Oct 17 '12 at 18:05
  • The memory keeps moving around, so getting the int here and there might have different results. You should Pin the address to the memory and then send the IntPtr's `.ToInt32()`. – SimpleVar Oct 17 '12 at 18:09
  • @cdhowie - I edited the question to show the documentation for the methods, as well as what VS says for them. – DanM7 Oct 17 '12 at 18:15
  • maybe you should use `int blobPointer = &p;`. Anyway I think it is strange to store image in a string, I suggest you to use byte[] or stream for it. As all above. Please look on http://bitmiracle.com/libtiff/. – user854301 Oct 17 '12 at 18:19
  • @cdhowie - Your suggestion to use the `Encoding` class to convert the string to a `byte[]` and get the `byte*` worked. Do you want to answer my question so I can mark that as answered? – DanM7 Oct 17 '12 at 18:58

1 Answers1

1

BlobToVariant probably expects a pointer-to-C-string; a char*. While char is a 1-byte data type in C, it is a 2-byte data type in C#. A C# char* and a C char* are different, incompatible types.

You will need to first convert the string to a sequence of bytes, using whatever text encoding is appropriate. I will use UTF-8 here, but you should switch to something else if this function doesn't accept UTF-8 input.

// "using System.Text;" assumed.
byte[] imageBlobBytes = Encoding.UTF8.GetBytes(imageBlob);

Now you do the same thing as you were doing, only you use a byte*, which corresponds to the char* type in C. (To be precise, they may differ in signed-ness. The C# byte type is unsigned, and the C char type is commonly signed, but we don't really care about that here.)

// 3rd Party ActiveX control for tiff image files
TIFFLib.TIFF tiff = new TIFFLib.TIFF();

// Variant object that will hold image
object blobVariant = new object();

unsafe
{
    fixed (byte* p = imageBlobBytes)
    {
        int blobPointer = (int)p;

        tiff.BlobToVariant(ref blobVariant, blobPointer);
        tiff.WriteVToFile(ref blobVariant);
    }
}

Note that this will only work on a 32-bit host, or on a 64-bit host if the process is executed as 32-bit. The C# int type is always 32 bits wide, while byte* will be 32 bits wide in a 32-bit execution environment, and 64 bits wide in a 64-bit execution environment. If executed in a 64-bit environment, this code will truncate the pointer and the resulting behavior will be undefined.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Thanks so much. Both informative and used part of my sample code. I wish I could do +2. Now I'm off to figure out the 32-bit issue... – DanM7 Oct 17 '12 at 19:34