CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Sep 2009
    Location
    North Carolina
    Posts
    52

    C# PInvoke Question

    Have a function as follows once I forage and translate everything into basic types:
    Code:
     unsigned int DAOpenDocument(HANDLE lphDoc, unsigned int dwSpecType, void* pSpec, unsigned int dwFlags);
    The documentation says that lphDoc is "a Pointer to a handle that will be filled with a value uniquely identifying the document to data access. The developer uses this handle in subsequent calls to data access to identify this particular input file. This is not an operating system file handle.
    Once I plugged this into P/Invoke Iterop Assistant I get:
    Code:
    public partial class NativeMethods {
        ///Return type: unsigned int
        ///lphDoc: HANDLE->void*
        ///dwSpecType: unsigned int
        ///pSpec: void*
        ///dwFlags: unsigned int
        {System.Runtime.InteropServices.DllImportAttribute("sccda.dll", EntryPoint="DAOpenDocument")]
        public static extern uint DAOpenDocument(System.IntPtr lphDoc, uint dwSpecType, System.IntPtr pSpec, uint dwFlags);
    }
    I use lphDoc = (System.IntPtr)GCHandle.Alloc(new Object(), GCHandlerType.Pinned);
    I know this allocates memory the sizeof Object, since I don't know what is going in there and I want it to be long lived, this seemed like a reasonable assumption. Is it?
    pSpec contains a file path which I've done before using System.IntPtr path = Marshal.StringToHGlobalAnsi(String filepath);

    Any better alternatives?
    Jim

  2. #2
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: C# PInvoke Question

    If you're talking about the Oracle API, then your signature is slightly wrong.

    Code:
    DAERR DAOpenDocument(
       VTLPHDOC   lphDoc,
       VTDWORD    dwSpecType,
       VTLPVOID   pSpec,
       VTDWORD    dwFlags);
    VTLPHDOC is typedeffed as

    Code:
    typedef VTSYSPARAM VTHDOC, * VTLPHDOC;
    where VTSYSPARAM is

    Code:
    typedef DWORD_PTR           VTSYSPARAM;
    Therefore your definition should be

    Code:
    [DllImport("sccda.dll",
        CallingConvention = CallingConvention.Winapi)]
    public extern static int DAOpenDocument(
        ref int phDoc,
        int dwSpecType,
        IntPtr pSpec,
        int dwFlags);
    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  3. #3
    Join Date
    May 2007
    Posts
    1,546

    Re: C# PInvoke Question

    I use lphDoc = (System.IntPtr)GCHandle.Alloc(new Object(), GCHandlerType.Pinned);
    If you just need a unique IntPtr, why not use an auto-incrementing integer?

    Code:
    public static class Id
    {
        static int value;
    
        public static IntPtr Next ()
        {
            int v = Interlocked.Increment (ref value);
            return new IntPtr (v);
        }
    }
    EDIT: I just looked at the docs and it's slightly confusing. There are two options that might be valid:
    1) You're supposed to generate the unique handle - in this case the above code is perfect.
    2) The library generates the unique handle in which case neither my code or your code will work.

    If option 2 is what's supposed to happen, you should probably be passing in something like:
    Code:
    IntPtr handle = IntPtr.Zero;
    DAOpenDocument(ref IntPtr phDoc, int dwSpecType, IntPtr pSpec, int dwFlags);
    Then when the call is finished, 'handle' will contain the unique identifier. The use of the word 'handle' and the declaration of the typedefs above make me suspect that it would be incorrect to treat it as a "ref int" as it's expecting a 'pointer to a handle' and handle generally means an IntPtr. So it wants a pointer to an IntPtr. You'd have to run your code on both a 32bit and 64bit system to be sure, or at least find the relevant typedefs in the documentation and paste them all here (just in case the above ones are incorrect).
    Last edited by Mutant_Fruit; March 9th, 2010 at 07:24 PM.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  4. #4
    Join Date
    Sep 2009
    Location
    North Carolina
    Posts
    52

    Re: C# PInvoke Question

    First, I am talking about the Oracle Outside In API. Specifically, I'm working on the Image Export (ix) implimentation.
    I originally did the reduction walk that darwen did (which is correct), but couldn't reconcile using an int with the documentation. Also I couldn't figure out what value to assign to it. MSDN says that a ref parameter must be initialized before use.
    BTW the new Object() thing didn't work. Got an error about non-blittable/non-primitive. Was reading this morning that GCHandle.Alloc is looking for an unmanaged object, not a class.
    I think that Mutant_Fruit is correct and that if I pass in a empty IntPtr the app will load it with an address of an appropriately sized buffer.
    In general, isn't it safe to assume that if the API doesn't tell you specifically the structure or at least the size of thing that is going to be at the other end of a pointer that the API itself is going to create the "thing" and give you a valid pointer?

    Well anyway I'll give it a try and get back. Thanks to both of you.

  5. #5
    Join Date
    Sep 2009
    Location
    North Carolina
    Posts
    52

    Re: C# PInvoke Question

    Hey, Mutant_Fruit we owe darwen an apology. Tried it with a IntPtr and got a 961 error from the API which I could not find in the header files. So I passed in an int initialized to 0 and got a success msg from DAOpenDocument.
    Looks like the API just wants an int to play with.
    Thanks,
    Jim

  6. #6
    Join Date
    May 2007
    Posts
    1,546

    Re: C# PInvoke Question

    Did you use "ref IntPtr" or just "IntPtr" ? Also, did you use "ref int" or "int"?

    I'm fairly sure it's "ref something" the only question is whether or not that something is an int or IntPtr. If you have a 32bit OS and 32bit software, then it doesn't matter. If it's a 64bit os with 64bit software, it will matter
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  7. #7
    Join Date
    Sep 2009
    Location
    North Carolina
    Posts
    52

    Re: C# PInvoke Question

    Did use "ref int". It is 32 libraries on 64 bit os. Developing on the machine it will run on.
    Jim

  8. #8
    Join Date
    May 2007
    Posts
    1,546

    Re: C# PInvoke Question

    As it's 32bit software, both "ref int" and "ref IntPtr" should work fine in this context. If the software were 64bit, that'd be another story

    If you do plan on using the 64bit software, do log this somewhere as a potential issue. Alternatively, get in touch with oracle/the oracle forums and ask people what you should be passing to that function.

    I suspect that it wants a pointer to a block of memory which is the size of a pointer.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured