Solved

Casting to IntPtr

Posted on 2004-04-04
25
1,207 Views
Last Modified: 2012-06-21
I need to make an implicit cast to IntPtr from an int *, but I can't do anything within either class. How can I do this?
0
Comment
Question by:derekthornton
  • 12
  • 6
  • 4
  • +2
25 Comments
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 10754551
You can't.  The .NET environment doesn't allow direct access to memory variables.  It helps to protect against buffer overruns.  

0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 10754552
You can't.  The .NET environment doesn't allow direct access to memory variables.  It helps to protect against buffer overruns.  

0
 
LVL 2

Author Comment

by:derekthornton
ID: 10754763
That isn't true in the slightest. You can use pointers in C#.
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10754766
And buffer overruns has nothing to do with it. Unsafe code is restricted for memory disposal reasons. You must compile code with an unsafe switch to use memory variables. But they work just fine in C# code. And for the task I need to perform, I have to use them. But I need to cast to and from an IntPtr, but the IntPtr library is sealed and cannot be inherited, so I cannot add an operator overload to it's class.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10755158
Please show your code. If int* points to managed object, such conversion may be dangerous because this object may be move by garbage collector.
0
 
LVL 20

Expert Comment

by:TheAvenger
ID: 10755481
Can you post the code so that we see how you use int* and in what kind of block?
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10755631
Post your code and describe what problem do you try to solve. .NET makes impossible getting unmanaged pointer to managed object because managed object may be moved by GC making unmanaged pointer invalid. To get unmanaged pointer (IntPtr) for API which points to some data, we need to use Marshal allocation functions like Marshal.AllocHGlobal Method.
See also this thread:

http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_20932459.html
0
 
LVL 20

Accepted Solution

by:
TheAvenger earned 500 total points
ID: 10755699
Alex, it is still possible to get an unmanaged pointer to a managed object using the fixed word. Check this example:

/// <summary> Bitwise XOR between corresponding bytes</summary>
/// <returns> An array of length = the smaller between arr1 and arr2
/// </returns>
public unsafe static byte[] XOR (byte[] arr1, byte[] arr2)
{
      int len = Math.Min (arr1.Length, arr2.Length);
      byte[] result = new byte[len];
      fixed (byte * bp1 = arr1)
            fixed (byte *bp2 = arr2)
                  fixed (byte *bres = result)
                  {
                        int *p1 = (int*)bp1;
                        int *p2 = (int*)bp2;
                        int *res = (int*)bres;
                        for (int i = 0; i < len / sizeof (int); i++)
                              res[i] = p1[i] ^ p2[i];
                  }

      for (int i = len - len % 4; i < len; i++)
            result[i] = (byte)(arr1[i] ^ arr2[i]);

      return result;
}
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756493
Err.. I have the casting conversion working just fine. The problem is with library access. I can't make an implicit operator to IntPtr because IntPtr is a .NET class and I cannot access it, and casting operators have to be within the class they modify. I already know how to do the conversion, I'm trying to figure out how to make it easier by providing an implicit cast to it.
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756512
i.e.

int * UnmanagedObject = // ...
IntPtr lpMyCoolStuff = ( Sturcture )  Marshal.PtrToStructure(  (IntPtr) UnmanagedObject , Structure );

This conversion works just fine. I just want to be able to type ...

IntPtr lpMyCoolStuff = UnmanagedObject instead though.
0
 
LVL 20

Expert Comment

by:TheAvenger
ID: 10756515
OK, if you don't want to share the code, try this: in C# you can convert without any loss the IntPtr to int like this:

int i;
IntPtr iptr;
....
iptr = (IntPtr)i;
i = (int)iptr;

Then you can move the value as if it's an int (which is also compatible with any kind of pointers in C/C++ for example)
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756521
I can post the code. It's just very long. Give me a few moments to gather up all that it requires.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 2

Author Comment

by:derekthornton
ID: 10756531
using System;
using System.Runtime;
using System.Runtime.InteropServices;

namespace TOCR
{

      unsafe public abstract class TOCRGetResults
      {

            #region Instance Fields

            /// <summary> The Starting Point of the Items </summary>
            private static IntPtr AddressOfItems;

            #endregion

            #region Constructor

            /// <summary> Retrieves the Results for a specific OCR Job </summary>
            /// <param name="JobNo"></param>
            /// <param name="ResultsStr"></param>
            public static void GetResults ( ref int JobNo , ref string ResultsStr )
            {
                  // The Size of the Results
                  int ResultsInf = 0;
                  // The Actual Results
                  int * TOCRResults = (int *)0;
                  // The Structured Results
                  TOCR.TOCRResults OCRResults = new TOCRResults();
                  // The Location of The Items Within the results
                  AddressOfItems = IntPtr.Zero;

                  // Allocate Memory for the Results
                  AllocateMemory ( ref JobNo, ref ResultsInf );
                  // Allocate the Results
                  AllocateResults ( ref JobNo, ref ResultsInf,ref TOCRResults );
                  // Determine the Difference between the Items and the Header
                  AllocateItemAddress ( TOCRResults , ref AddressOfItems );
                  // Allocate the Header
                  AllocateHeader ( TOCRResults, ref OCRResults );
                  // Allocate the Items
                  AllocateItems ( TOCRResults, ref OCRResults );
                  // Build the Results String
                  BuildString ( ref OCRResults, ref ResultsStr );

            }

            #endregion

            #region Private Methods

            #region Memory Allocation

            /// <summary> Allocates the memory needed for the OCR Job Results </summary>
            /// <param name="JobNo"></param>
            /// <param name="ResultsInf"></param>
            private static void AllocateMemory ( ref int JobNo, ref int ResultsInf )
            {
                  // Determine the needed memory size
                  API.TOCRGetJobResults ( JobNo, ref ResultsInf, IntPtr.Zero );
            }

            /// <summary> Allocates the OCR Results to the correct memory address </summary>
            /// <param name="JobNo"></param>
            /// <param name="ResultsInfo"></param>
            /// <param name="TOCRResults"></param>
            private static void AllocateResults ( ref int JobNo, ref int ResultsInf, ref int * TOCRResults )
            {
                  // Allocate the memory
                  TOCRResults = (int *)Marshal.AllocHGlobal ( (int) ResultsInf );
                  // Allocate the OCR Results to the reserved memory address
                  API.TOCRGetJobResults ( JobNo, ref ResultsInf, TOCRResults );
            }

            #endregion

            #region Memory Shifting

            /// <summary> Determines where the Header ends and the items begin </summary>
            /// <param name="TOCRResults"></param>
            /// <param name="ItemAddress"></param>
            private static void AllocateItemAddress ( int * TOCRResults, ref IntPtr ItemAddress )
            {
                  ItemAddress = ( IntPtr )
                        ( (int) ( TOCRResults ) +
                        Marshal.SizeOf ( typeof ( TOCRResultsHeader ) ) );
            }

            /// <summary> Allocate the Header Data </summary>
            /// <param name="TOCRResults"></param>
            /// <param name="OCRResults"></param>
            private static void AllocateHeader ( int * TOCRResults , ref TOCRResults OCRResults )
            {
                  // Convert the appropriate parts of the memory to a TOCRResultsHeader object
                  OCRResults.Hdr = ( TOCRResultsHeader )
                        Marshal.PtrToStructure ( (IntPtr) TOCRResults , typeof ( TOCRResultsHeader ) );
            }

            /// <summary> Allocate the Item Data </summary>
            /// <param name="TOCRResults"></param>
            /// <param name="OCRResults"></param>
            private static void AllocateItems ( int * TOCRResults, ref TOCRResults OCRResults )
            {
                  OCRResults.Item = ( TOCRResultsItem )
                        Marshal.PtrToStructure (
                        AddressOfItems,
                        typeof ( TOCRResultsItem ) );
            }

            #endregion

            #region Item Assignment

            /// <summary> Increment the Item Location </summary>
            /// <param name="Item"></param>
            /// <param name="Offset"></param>
            private static void OffsetItem ( ref TOCRResultsItem Item, int Offset )
            {
                  Item = ( TOCRResultsItem )
                        Marshal.PtrToStructure (
                        (IntPtr)( (int) AddressOfItems + Offset * Marshal.SizeOf(typeof ( TOCRResultsItem ) ) ) ,
                        typeof( TOCRResultsItem ) );
            }

            /// <summary> Builds the complete string to return </summary>
            /// <param name="OCRResults"></param>
            /// <param name="ResultsStr"></param>
            private static void BuildString ( ref TOCRResults OCRResults, ref string ResultsStr )
            {
                  for ( int i = 0; i < OCRResults.Hdr.NumItems ; i++ )
                  {
                        OffsetItem ( ref OCRResults.Item, i );
                        ResultsStr += OCRResults.Item.ToString();
                  }
            }
            
            #endregion

            #endregion

      }

}
0
 
LVL 20

Expert Comment

by:TheAvenger
ID: 10756542
What happens if you use directly:

IntPtr lpMyCoolStuff = (IntPtr)UnmanagedObject;
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756546
It doesn't work. See the code above. I have to seperate the pointer out into two objects.
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756579
TOCRGetResults takes a JobNumber, and two other variables. If the third parameter is null or 0, then it sets the second parameter equal to the number of bytes needed to allocate in memory for OCR Results. If the third parameter is a pointer to a memory address,it allocates the Results to that memory Address. I've done this same code with IntPtr, and It works, but there is very heavy data loss in between.

I have to then split the int * up into a TOCRResultsHeader and Multiple TOCRResultsItem structures from there, using the Size of a TOCRResultsHeader as an offset with the Item Number to get the appropriate memory address. The code WORKS fine, I just want ot make it CLEANER.
0
 
LVL 20

Expert Comment

by:TheAvenger
ID: 10756602
OK, I see. I don't think however that you have another chance to make it. In the best case you can make a method that will execute the same and then call

IntPtr lpMyCoolStuff = MyMethod (UnmanagedObject);

and inside MyMethod do exactly the same you are making at the moment. This will just simplify the sintax a little bit
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756618
Of course. But making the syntax more simple is a considerable thing, since difficult to read code is just a breeding ground for more bugs.
I'd basically like to be able to do an implicit cast through IntPtr/int *.
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756719
And yes, I know this code may be messed up by the garbage collector. However it's the only way to make this thing work right.
0
 
LVL 2

Author Comment

by:derekthornton
ID: 10756839
( IntPtr ) ( (int) (lpItem) + Marshal.SizeOf( typeof ( TOCRResultsHeader ) )

this code here is more or less what I'm looking to simplify.
0
 
LVL 20

Expert Comment

by:TheAvenger
ID: 10756856
Unfortunately I am not sure I can help you with something else :-(( Hope somebody else helps...
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10756960
derekthornton, maybe you can write simple prototype which shows what you want to do, what version works and what version doesn't work. I don't understand your code, maybe simple code which demonstrates the problem without unnecessary details can help.
0
 

Expert Comment

by:BillyX
ID: 10793876
Hello! It seems that you two are very good at this thing, could you please have a look at my question:
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/Q_20949171.html

It has been here for 21 days without an answer :-(
0
 
LVL 2

Author Comment

by:derekthornton
ID: 11152109
AlexFM. I'm sorry I haven't replied. I sort of gave up hope on this question, but your answers were all very helpful for a lot of things. I'm not sure what to do. Should I still give the points and close the question?
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 11152577
If you got satisfactory answer, accept it. If not, ask Community Support to close this question.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now