none
P invoke from entry point RRS feed

  • Question

  • I'm trying to invoke some code based on an entry point but "no luck so far"

    Based on a tute calling functions I came about this far..

        <DllImport("mydll.dll")>
        Public Shared Function SuperDuperEntryPoint() As Integer
        End Function

    My entry point is called SuperDuperEntryPoint

    And looks like,

    SuperDuperEntryPoint proc hInstDLL:DWORD, fdwReason:DWORD, lpvReserved:DWORD



    • Edited by Naampie2000 Saturday, June 24, 2017 6:56 PM
    Saturday, June 24, 2017 6:55 PM

All replies

  • You did not set parameters for the function in your DllImport sample.
    Saturday, June 24, 2017 7:05 PM
  • Maybe I'm looking at it the wrong way?..

    So I have some variables in the .data section of my dll. And I did this. But still no go.

    <DllImport("mydll.dll")>   

    Public Shared Function SuperDuperEntryPoint(ByRef szLoading As Byte, ByRef szUnloading As Byte, ByRef szOrdinal As Byte) As Integer       

    thisA = szLoading       

    thisB = szUnloading       

    thisC = szOrdinal   

    End Function

    This looks right to me :|

    P.s. Probably can't pass by reference here, 


    • Edited by Naampie2000 Saturday, June 24, 2017 9:38 PM
    Saturday, June 24, 2017 9:30 PM
  • This looks right to me :|

    "no luck so far" or "still no go" is not sufficient description.  You need to show what the problem is.  Is the problem with declaring the function, or with calling it?   Is there an error message?  If so, it will describe the problem and indicate what you need to do to fix it.  Otherwise, you need to describe exactly what the issue is that you have with that code. There should not be any code in your function.

    Saturday, June 24, 2017 10:20 PM
  • It's not allowed to pass variables to variables inside the p-invoke function body.

    so..

    thisA = szLoading       

    thisB = szUnloading       

    thisC = szOrdinal   

    Is not allowed.

    Saturday, June 24, 2017 11:13 PM
  • It's not allowed to pass variables to variables inside the p-invoke function body.

    That's correct.  It's not allowed - that code should not be there.  Your code should have stayed as you first posted it.   But you still haven't described the problem.

    Saturday, June 24, 2017 11:31 PM
  • I want to test my function by passing some variables from the dll to another class. Or more precise pass the .data section from the dll to and from my .net application, by calling the entry point once and mooching off the loaded registers. And loading them into public variables to pass them between classes.


    Saturday, June 24, 2017 11:54 PM
  • I want to test my function by passing some variables from the dll to another class. Or more precise pass the .data section from the dll to and from my .net application, by calling the entry point once and mooching off the loaded registers. And loading them into public variables to pass them between classes.

    What happens when you try?  Show the code you are using to call the function - that seems to be where the problem is.  Most of the above description seems unrelated to the function you have posted.

    Sunday, June 25, 2017 1:27 AM
  • I don't think that is the problem.  Just the way of writing the invoke function is new to me. And I need to trust my function invokes once to get all the variables. "in different classes"

    This is it.

        <DllImport("mydll.dll")>
        Public Shared Function SuperDuperEntryPoint(ByRef szLoading As Byte, ByRef szUnloading As Byte, ByRef szOrdinal As Byte) As Integer
            thisA = szLoading
            thisB = szUnloading
            thisC = szOrdinal
        End Function


    Sunday, June 25, 2017 10:32 AM
  • I don't think that is the problem.  Just the way of writing the invoke function is new to me.

    If you decorate your function definition with the DllImport attribute then you do not include code within the function.  The DllImport attribute tells the compiler that the code to be executed for that function is in the DLL method.   Remove that code from within the function - it should not be there.

    What do you mean by 'invoke function'?  If you are referring to calling your function, then that doesn't change.  Post the code you are using to call the function, and describe what error you get, or why you believe there is a problem.


    • Edited by Acamar Sunday, June 25, 2017 10:52 AM fmt
    Sunday, June 25, 2017 10:50 AM
  • It's more of now I have called the dll. But my code is wrong  because I can't pass variables like this inside the invoke module body "right?"

    So my question is how do I pass these variables then? What code do I need to get reference to the .data section of the dll, from other points in my code, without invoking the dll again (on any instance), just how do I point to these new variables?


    Sunday, June 25, 2017 11:16 AM
  • Is the unmanaged DLL yours?  If so then simply export an unmanaged function that returns the data of interest in a known structure.  P/Invoke the function once from your managed code to retrieve the structure that contains the data of interest.

    Sunday, June 25, 2017 11:29 AM
  • Yes it's mine, or an example masm dll at least. So I have to invoke the entry point. But the entry must also contain the header "struct" that passes the variables?

       <DllImport("mydll.dll")>
        Public Shared Function SuperDuperEntryPoint(ByRef szLoading As Byte, ByRef szUnloading As Byte, ByRef szOrdinal As Byte) As Integer
        End Function

    It would look something like this, right?

    But now I don't have access to these variables, they are inside the function dll import. How would this code look then?

    Sunday, June 25, 2017 11:36 AM
  • So my question is how do I pass these variables then?

    Exactly as you would for any other function -

    Dim Result As Integer = SuperDuperEntryPoint(Val1, Val2, Val3)

    That's likely the code that has the problem, but you won't show what it is, so it is impossible to know how to fix it.

    Sunday, June 25, 2017 11:52 AM
  • Acamar what are you talking about?,

    I want the entire header not a return value.

    Sunday, June 25, 2017 1:38 PM
  • Heres an example of a VB console program using P/Invoke to retrieve a data structure from a Dll written in C/C++. All error checking has been omitted.

    DLL Header -

    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the MYDATA_EXPORTS
    // symbol defined on the command line. This symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // MYDATA_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef MYDATA_EXPORTS
    #define MYDATA_API __declspec(dllexport)
    #else
    #define MYDATA_API __declspec(dllimport)
    #endif
    
    typedef struct {
    	LPWSTR   pszFirstname;
    	LPWSTR   pszLastName;
    	int		 iAge;
    } MYDATA, *PMYDATA;
    
    MYDATA_API void GetStruct(PMYDATA pdata);
    
    


    DLL code -

    // MyData.cpp : Defines the exported functions for the DLL application.
    //
    
    #include "stdafx.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #include "MyData.h"
    
    #ifdef __cplusplus
    }
    #endif
    
    MYDATA data =
    {
    	L"Mickey",
    	L"Mouse",
    	18
    };
    
    
    MYDATA_API void GetStruct(PMYDATA pdata)
    {
        pdata->pszFirstname = data.pszFirstname;
    	pdata->pszLastName = data.pszLastName;
    	pdata->iAge = data.iAge;
    }
    
    

    VB Console program -

    Imports System.Runtime.InteropServices
    
    Public Class MYDATADLL
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
        Public Structure MyData
            <MarshalAs(UnmanagedType.LPWStr)>
            Public Firstname As String
            <MarshalAs(UnmanagedType.LPWStr)>
            Public Lastname As String
            Public Age As Integer
        End Structure
    
        <DllImport("MyData.dll", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode, EntryPoint:="GetStruct", ExactSpelling:=True)>
        Public Shared Sub GetStruct(ByVal data As IntPtr)
        End Sub
    End Class
    
    Module Module1
    
    
        Sub Main()
            Dim pdata As IntPtr
            Dim mdata As MYDATADLL.MyData
    
            pdata = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(MYDATADLL.MyData)))
    
            MYDATADLL.GetStruct(pdata)
    
            mdata = Marshal.PtrToStructure(pdata, GetType(MYDATADLL.MyData))
    
            Console.WriteLine("First Name {0}, Last Name {1}, Age {2}", mdata.Firstname, mdata.Lastname, mdata.Age)
    
            Marshal.FreeHGlobal(pdata)
    
        End Sub
    
    End Module
    

    Sunday, June 25, 2017 2:39 PM
  • Thanks!

    Looks pretty hard tho :) Need to study it for a bit.

    Sunday, June 25, 2017 3:10 PM
  • So if I understand correctly, this creates a C header file implementing a struct. Which then is read out as a pointer with increments? So consequently a pointer to my entry points data formatted as a struct. 

    But what I don't understand is when I call the masm entry point the values of interest are right there, why can't I use those then?

      <DllImport("mydll.dll")>
        Public Shared Function SuperDuperEntryPoint(ByVal szLoading as byte,) As Integer
        End Function

    "So I presume the code I called starts running at a much higher frequency than the GUI application running it, and the data is always fresh enough in ram at the time the GUI tries to read it from RAM"

    Or maybe am I better off using something like a marshal pointer to memory kind of setup? Getting only the base address and adding integers to it. If that's even possible?


    Sunday, June 25, 2017 9:38 PM
  • I want the entire header not a return value.

    The return value is determined by the DLL.  The definition of the function return value has to match that. If you declare the return value as an integer, you are saying that that's what you are expecting to get.  

       Public Shared Function SuperDuperEntryPoint(ByRef szLoading As Byte, ByRef szUnloading As Byte, ByRef szOrdinal As Byte) As Integer

    If the DLL is actually returning something else, then the function definition has to show that.  You have defined the function to return an integer, so that's how you call it.

    If you show some detail of the DLL it may be possible to determine what it is actually returning, and adjust the function definition (and the function call) to match that.

    Sunday, June 25, 2017 9:40 PM
  • Thanks for the reply,

    The dll is not created yet, but sports Direct Sound, ASIO and a DSP thread,

    In this case the dll has it's own loop at ~96Khz (samplerate) will the struct continue to reflect the actual status of the dll?

    Sunday, June 25, 2017 10:02 PM
  • In this case the dll has it's own loop at ~96Khz (samplerate) will the struct continue to reflect the actual status of the dll?

    It seems that your question is about how to create a DLL, not how to access it from VB .Net.

    A structure is a mechanism for returning multiple fields from a function.  The function returns the address of a region of memory, and the calling application uses the structure to access defined areas within that region. You can lock the memory so that the DLL can continue to update it, but there are probably better ways.

    You can allocate 'shared' unmanaged memory that is updated by the DLL and is accessible to your application. For an example see here:
    https://msdn.microsoft.com/en-us/library/system.io.unmanagedmemorystream%28v=vs.110%29.aspx?

    VB does not support pointers, so accessing 'fields' within a shared region is difficult. There is an accessor class that can be used:
    https://msdn.microsoft.com/en-us/library/system.io.unmanagedmemoryaccessor(v=vs.110).aspx

    Sunday, June 25, 2017 11:16 PM
  • Pff, and I was hoping itt'd be done by then.

    Thx for the reply :)

    Tuesday, June 27, 2017 1:04 PM