Results 1 to 16 of 16

Thread: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Hello -

    I used to use DllImport to call an external/unmanaged function as follows ...

    Private Declare Function Function_Delegate_A Lib "C:\Program Files\ABC\XYZ.dll" Alias "External_Function" _
    (ByRef ArgumentA As TypeA, _
    ByVal ArgumentB As Byte) As Return_Type


    This worked fine but I had to make the location of the *.dll dynamic so I changed it to ...

    Private Delegate Function Function_Delegate_B(ByRef ArgumentA as TypeA, _
    ByVal ArgumentB as Byte) As Return_Type


    mFunctionPointer = NativeMethods.GetProcAddress(mExternalLibraryPath, "External_Function")
    mFunctionPointerDelegate = DirectCast(Marshal.GetDelegateForFunctionPointer(mFunctionPointer, GetType(Function_Delegate_B)), Function_Delegate_B)

    Dim XYZ As Return_Type = mFunctionPointerDelegate.Invoke(A, B)


    This returns complete garbage for XYZ.

    I read in several related posts that you cannot return a struct from a function but where in the .NET documentation does it state that … and why did this work with DllImport?

    Thanks,
    Joe

  2. #2
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    I'm sorry but I don't understand "had to make the location of the *.dll dynamic". As you've kinda proved that that way madness lies it seems to be time to rethink that!

    I don't really see much hope of the second method working. It seems to reference all kinds of undeclared and undefined stuff. There is certainly no injunction on returning a structure from a function. Windows would be dead in the water if you couldn't!
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    The problem is that the *.dll is in a location that is determined at run-time ... hence "dynamic". The mechanism I used is well-documented and works for everything else ... except when a function returns a Structure. Here is what that looks like ...

    <StructLayout(LayoutKind.Explicit)> _
    Public Structure Return_Type
    <FieldOffset(0)> Dim ValueA As Single
    <FieldOffset(4)> Dim ValueB As Single
    End Structure

    The other variables are ...

    mFunctionPointer As IntPtr = IntPtr.Zero
    mFunctionPointerDelegate As Function_Delegate_B = Nothing

    Thanks,
    Joe

  4. #4
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    I'm not 100% sure but I think you need to use the MarshalAsAttribute on the return type.
    Code:
      Private Delegate Function Function_Delegate_B(ByRef ArgumentA As TypeA, _
        ByVal ArgumentB As Byte) As <MarshalAs(UnmanagedType.Struct)> Return_Type
    Or possibly use UnmanagedType.LPStruct.

    I don't think I ever used any p/invoke on any function that have returned a struct.
    Last edited by Joacim Andersson; Mar 21st, 2013 at 09:47 PM.

  5. #5
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Quote Originally Posted by Joacim Andersson View Post
    I don't think I ever used any p/invoke on any function that have returned a struct.
    Well certainly not a Win32 API function. MS prefers passing back structures through parameters and reserving the return value as a means to determine success or failure of the function itself. However, the OP may be trying to call an exported function that is not of the Win32 API in which case all bets are off. While on that topic, I would expect it to return a pointer to a structure. It would be nice if the OP could post the C signature of the function he is trying to call.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #6
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    I actually doubt that the function returns a pointer to a struct since it has to use malloc to be able to get the struct onto the heap, who is responsible for releasing that memory? There is no way you can construct a local struct in a C/C++ function and then return a pointer to that since then you would get a pointer to a location on the stack that has been popped when the function returns. Nasty things will happen in either case.

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    @Joacim
    Thanks a lot ... I just tried the UnmanagedType.Struct but nothing changed. I also tried the UnmanagedType.LPStruct but that just caused a crash.

    Thanks,
    Joe

  8. #8
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    LPStruct should crash if the function doesn't return a pointer to the struct, which I doubted to begin with.

    Do you have the signature for the C function?

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    @Niya
    The *.dll is actually in Ada so I didn't want to "scare" folks with the interface but here we go ...

    type Type_A
    is record
    A : Float;
    ...
    end record;

    type Return_Type
    is record
    A : Float;
    B : Float;
    end record;

    function External_Function()
    ( ArgumentA : in Type_A;
    ArgumentB : in Boolean := False
    ) return Return_Type;

    pragma Export (C, External_Function, "External_Function");

    The problem is that I don't have much control over that interface. There are also other (working) functions that use an "out" in the Ada interface to return a structure by reference through an argument.

    I also forgot to mention that I use the following for the Private Delegate Function ...
    <UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet:=CharSet.Ansi)> _

    and (unsuccessfully) tried the CallingConvention.Cdecl as well.

    I saw that I could use Marshal.PtrToStructure if the function returned a pointer but unfortunately I don't have much control over the interface.

    Thanks,
    Joe




  10. #10
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Have you tried using Marshal.PtrToStructure? In which case you must change the signature for your delegate to accept an IntPtr as the return type.

  11. #11

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Quote Originally Posted by Joacim Andersson View Post
    LPStruct should crash if the function doesn't return a pointer to the struct, which I doubted to begin with.

    Do you have the signature for the C function?
    Makes sense. See below for the Ada interface.

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Quote Originally Posted by Joacim Andersson View Post
    Have you tried using Marshal.PtrToStructure? In which case you must change the signature for your delegate to accept an IntPtr as the return type.
    Yes ... I already tried that but it resulted in a crash. Probably because the Ada code isn't returning a pointer.

    Thanks,
    Joe

  13. #13
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Alright, I'm out of ideas unless you can create a wrapper function in another DLL that will call this function and return the struct as an out parameter.

  14. #14

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Quote Originally Posted by Joacim Andersson View Post
    Alright, I'm out of ideas unless you can create a wrapper function in another DLL that will call this function and return the struct as an out parameter.
    That might be something to look into but maybe I can get an updated version of the *.dll too. I certainly appreciate your help!

    Thanks,
    Joe

  15. #15
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    I've had a play with this with some success.

    Seeing as we already have some ADA posted in this thread, I'm going to post the C# I used. I did translate it using this translator but it looked awful, so I'll leave that to someone else.
    Code:
    using System;
    using System.Runtime.InteropServices;
    using System.Drawing;
    Helper class wrapping LoadLibrary API
    Code:
        class NativeLibrary
        {
            [DllImport("kernel32.dll")]
            static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
            [DllImport("kernel32.dll")]
            static extern IntPtr LoadLibrary(string libraryName);
            [DllImport("kernel32.dll")]
            static extern int FreeLibrary(IntPtr hModule);
    
            IntPtr handle;
    
            public NativeLibrary(string libraryName)
            {
                handle = LoadLibrary(libraryName);
                if (handle == IntPtr.Zero)
                    throw new ArgumentException(string.Format("Failed to load \"{0}\"", libraryName));
            }
            public void Free()
            {
                FreeLibrary(handle);
                handle = IntPtr.Zero;
            }
            public object CreateDelegate(string procedureName, Type type)
            {
                var func = GetProcAddress(handle, procedureName);
                if (func == IntPtr.Zero)
                    throw new ArgumentException(string.Format("Failed to find procedure \"{0}\"", procedureName));
                return Marshal.GetDelegateForFunctionPointer(func, type);
            }  
        }
    Example use of class above to wrap test API.
    Code:
        class LibXWrapper
        {
            public delegate float PassVal_(PointF pt);
            public delegate float PassRef_(ref PointF pt); 
            public delegate float PassPtr_(ref PointF pt);
            public delegate PointF RetVal_(float n);
            public delegate IntPtr RetRef_(ref PointF pt);
            public delegate IntPtr RetPtr_(ref PointF pt);
    
            NativeLibrary lib;
            public LibXWrapper( string libraryPath )
            {
                lib = new NativeLibrary(libraryPath);
    
                PassVal = (PassVal_)lib.CreateDelegate("ByVal_", typeof(PassVal_));
                PassRef = (PassRef_)lib.CreateDelegate("ByRef_", typeof(PassRef_));
                PassPtr = (PassPtr_)lib.CreateDelegate("ByPtr_", typeof(PassPtr_));
                RetVal = (RetVal_)lib.CreateDelegate("RetVal_", typeof(RetVal_));
                RetRef = (RetRef_)lib.CreateDelegate("RetRef_", typeof(RetRef_));
                RetPtr = (RetPtr_)lib.CreateDelegate("RetPtr_", typeof(RetPtr_));
            }
    
            public PassVal_ PassVal { get; private set; }
            public PassRef_ PassRef { get; private set; }
            public PassPtr_ PassPtr { get; private set; }
            public RetVal_ RetVal { get; private set; }
            public RetRef_ RetRef { get; private set; }
            public RetPtr_ RetPtr { get; private set; }
        }
    The DLL header for the test API
    Code:
    #pragma once
    
    extern "C"
    {
    	struct pointF
    	{
    		float x, y;
    	};
    
    	__declspec( dllexport )  float ByVal_(pointF);
    	__declspec( dllexport ) float ByRef_(pointF&);
    	__declspec( dllexport ) float ByPtr_(pointF*);
    
    	__declspec( dllexport ) pointF  RetVal_(float);
    	__declspec( dllexport ) pointF& RetRef_(pointF*);
    	__declspec( dllexport ) pointF* RetPtr_(pointF*);
    
    }
    W o t . S i g

  16. #16

    Thread Starter
    Junior Member
    Join Date
    Oct 2010
    Posts
    28

    Re: Marshal.GetDelegateForFunctionPointer() Problem w/ Function returning Struct

    Wow ... thanks for taking the time to play with this. I'll give ita try using my Ada *.dll as soon as I get a chance ...

    Thanks,
    Joe

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