Page 2 of 2 FirstFirst 12
Results 41 to 63 of 63

Thread: [VB6] Call Functions By Pointer (Universall DLL Calls)

  1. #41
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Dear Lavolpe,

    Swapping of vtables of member functions works fine provided we find their correct vtable offset.Regarding
    offsets you helped a lot to find out offset of member functions using zProbe for which I am thankful to you.

    But when I try to replace vtables of member functions with different protrotypes with different parameters and different return types the application crashes.

    Can you provide me

    1.a generic example code of how to handle this issue without crashing the application.

    2.how to handle different calling conventions _cdecl in VB without crash when I replace the vtable member function with module function.

    You can help me using my old class_vs_forms_vtable.zip which I am attaching.
    It is a standard exe project with member functions having same prototype.

    Thanking you once again.
    regards,
    Jsvenu
    Attached Files Attached Files

  2. #42
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    EDIT1: Hey, going through DispCallFunc has become pretty moot for what I was trying to do. Other far superior alternatives have emerged. So ... you can ignore this, if you like. Also, I haven't seen you around for a few days. I hope all is well. I'll imagine you're enjoying a piƱa colada on some Caribbean beach until I hear otherwise.


    Say Keith,

    I suspect you've been watching what I'm messing with regarding the Cairo Graphics. I'm just wondering how this DispCallFunc wrapper (for CDECL) would handle a String return. For instance...

    Code:
    
    cairo_public const char *
    cairo_status_to_string (cairo_status_t status);
    
    

    ...how could we handle that? I scanned the posts in this thread and didn't see anything, although I could have missed it. Also, the "status" is just a Long. It seems that this library has a typedef for just about everything.

    Also, at the moment, I can't tell you whether it's ANSI (or ASCII) or Unicode. If it's Unicode, it's probably UTF-8, but that's yet another problem. First, I just need to get it into VB6, and then I'll figure out how to "translate" it to UCS-2-Unicode. I don't think these Cairo functions are anything where speed would be a concern, but there are a handful of them that return Strings.

    Thanks,
    Elroy
    Last edited by Elroy; Aug 17th, 2018 at 08:53 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  3. #43
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    @jsvenu - You can't replace vtable functions with different function prototypes.. (different parameter counts or parameter types)
    That breaks the interface contract, which every call is expecting.
    Every COM Object is required to abide by an agreed upon interface definition.

  4. #44

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Just FYI: DispCallFunc can handle CDECL, it does more than just StdCall. The convention type is one of the parameters to that API. A helper/thunk may be needed for CDECL callbacks into a VB project, but I don't think you were asking about that.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #45
    Hyperactive Member
    Join Date
    Jan 2018
    Posts
    264

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    I was looking back into doing some CDECL calls, and tried this out. Surprisingly, it didn't work. The comments mention calling methods by ordinal, but I don't see a way to do that. One of Paul Caton's procedures had a simple solution:

    Code:
    Private Declare Function GetProcByOrdinal Lib "kernel32" Alias "GetProcAddress" (ByVal hModule As Long, ByVal nOrdinal As Long) As Long
    .
    .
        If Left$(FunctionName, 1) = "#" Then
            fPtr = GetProcByOrdinal(hMod, CLng(Mid$(FunctionName, 2))) ' get the function pointer by ordinal #
        Else
            fPtr = GetProcAddress(hMod, FunctionName)           ' get the function pointer (Case-Sensitive)
        End If

  6. #46
    New Member
    Join Date
    Apr 2019
    Posts
    5

    Exclamation Re: [VB6] Call Functions By Pointer (Universall DLL Calls) - VarType issues

    Quote Originally Posted by LaVolpe View Post
    ...
    The attachment includes very simple examples of calling DLL functions and calling a COM virtual function.
    ...
    Thanks for providing this code.

    Just a word of warning to VBA developers, and other developers that access a VarType function that has the same 'unusual' behaviour that VBA's VarType function has, you may have to use code similar to the following code to properly get each variable's type:
    Code:
    vParamType(pIndex) = IIf(TypeOf vParams(pIndex) Is Object , _
                                           VbVarType.vbObject, _
                                           VarType(vParams(pIndex))                                             
                                          )
    The reason why this may be the case, can be garnered by looking at the StackOverflow question & answers posted here.

    I've created a pull request shown here, to make VBA's VarType documentation more clear regarding these issues.

    I couldn't tell whether VB6 was affected by these issues. I think the VB6 documentation for VB6's VarType function might be shown here, but I couldn't tell for certain.

    EDIT: Have now discovered that official VB6 documentation is hosted by Microsoft here.

    Regards.
    Last edited by MarkFern; Apr 17th, 2019 at 06:52 AM. Reason: 1. Coding mistake. 2. Found VB6 documentation.

  7. #47
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    @MarkFern: TypeOf VarType(vParams(pIndex)) Is Object makes no sense. Just use IsObject function like this:

    Code:
        If IsObject(vParams(pIndex)) Then
            vParamType(pIndex) = vbObject
        Else
            vParamType(pIndex) = VarType(vParams(pIndex))
        End If
    Note that converting this to a single expression w/ IIf has the side-effect of always evaluating VarType(vParams(pIndex)) which has the side-effect of always calling the default property/method of the object which for Word.Application instances can be an expensive out-of-process call.

    VarType is not unique and evaluating default property is a standard behaviour, even built-in Array(oMyInstance1, oMyInstance2, ...) does it and this is very welcome side-effect because when you have an instance of a Recordset for instance and you try to wrap Array(rs!ID, rs!Name, rs!Address) you don't want the ADODB.Fields in this array but only their default Value property. If you pass the naked ADODB.Fields you risk rs.MoveNext actually *changing* the values in the array. Now *that* would be a big surprise!

    cheers,
    </wqw>

  8. #48
    New Member
    Join Date
    Apr 2019
    Posts
    5

    Red face Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    @wqweto: Thanks for your useful reply.

    Quote Originally Posted by wqweto View Post
    @MarkFern: TypeOf VarType(vParams(pIndex)) Is Object makes no sense...
    I made a coding mistake - should have written TypeOf vParams(pIndex) Is Object instead. TypeOf... Is Object works in VBA & VB6 - the VB6 version of the TypeOf operator is documented here. IsObject() could be more efficient though - don't know.

    Have now discovered that official VB6 documentation is hosted by Microsoft here however, it seems to be accidentally missing documentation on VB6's VarType function.

    Thank you for pointing out the side-effect of IIf. I never thought about this before but of course it makes perfect sense. I just wanted to abbreviate my code more by using the function.

    Quote Originally Posted by wqweto View Post
    ...
    VarType is not unique and evaluating default property is a standard behaviour, even built-in Array(oMyInstance1, oMyInstance2, ...) does it and this is very welcome side-effect because when you have an instance of a Recordset for instance and you try to wrap Array(rs!ID, rs!Name, rs!Address) you don't want the ADODB.Fields in this array but only their default Value property. ...
    I can understand the benefit in regard to code like rs!ID but to me, such behaviour in VarType() is counter-intuitive. It tripped-up myself and probably also @LaVolpe. However, I completely admit that perhaps I don't understand VB & COM well enough to understand the benefits of such functionality. Thank you so much for explaining more about this.

    Thanks.
    Last edited by MarkFern; Apr 22nd, 2019 at 06:28 AM. Reason: Made reply more useful by reducing content & by adding some content regarding certain VB6 functions

  9. #49
    New Member
    Join Date
    Apr 2019
    Posts
    5

    Exclamation Re: [VB6] Call Functions By Pointer (Universall DLL Calls) - Bug / Issue

    Quote Originally Posted by LaVolpe View Post
    I was recently made aware that a function I've used from time to time for calling virtual functions of COM objects ... So, I whipped up a 'generic' class that can call both standard DLL functions & COM VTable functions.
    ...
    Variant parameter bug / issue

    I have found a problem with using the/a version of @LaVolpe's code available on 23rd May 2019, to call COM object methods that have VARIANT parameters.

    Within VB6 & VBA7 (close to what a VB7 would be), the VarType function never returns a value indicating that the passed argument is a non-array Variant value. However, for some COM method calls, the method parameters have to have this type. This appears to trip-up @LaVolpe's code.

    You can test this with the Equals method of the Object class of the mscorlib COM library for the .NET framework. You can also test it with the Invoke_2 & Invoke_3 methods of the MethodInfo class of the same library.

    If you manually intervene to choose the vbVariant type for the VARIANT parameters, @LaVolpe's code works.



    Code to handle issue

    I've drawn up VB code to handle such situations which I've attached at the bottom. The code was first written for VBA7 (close to what a VB7 would be) but should also hopefully work under VB6 when the environment is 32 bit. I did try to install VB6 to test the code under VB6, but couldn't figure out how to easily install VB6 under Windows 8.1.

    COMObjectVirtualMethodTable.bas
    Last edited by MarkFern; Jun 7th, 2019 at 02:45 AM. Reason: VBA isn't VB7 but instead close to what a VB7 would be

  10. #50
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    This is the new link to IShell in Bonnie West's post #5.

    https://fossies.org/dox/wine-4.0.1/i...ShellItem.html

  11. #51
    New Member
    Join Date
    Dec 2019
    Posts
    2

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    I'm trying to get this to work for a standard DLL built in VB6.

    The following code works as intended (returns input+1)
    Code:
    Private Declare Function VBDLLDemo Lib "Project1.dll" (lSource As Long) As Long
    Private Sub Form_Load()
        MsgBox VBDLLDemo(5)
    End Sub
    Which we get 6 as the output.

    Trying to run the following equivalent command:
    Code:
    lLen = c.CallFunction_DLL("Project1.dll", "VBDLLDemo", STR_NONE, CR_LONG, CC_STDCALL, CLng(5))
    msgbox lLen
    and ideally, I would get 6. Instead the entire IDE crashes likely due to memory read error. Both the hMod and fPtr are valid inside the function.

    I'd be happy for any input you might have, and it's good to see someone still coding in VB6 as well.

  12. #52

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    You cannot call ActiveX DLLs as you would standard DLLs. VB builds ActiveX not standard DLLs
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  13. #53
    New Member
    Join Date
    Dec 2019
    Posts
    2

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Thanks, following instructions to compile a standard DLL in vb6 solved the issue.

  14. #54
    New Member
    Join Date
    Dec 2019
    Posts
    1

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Hi LaVolpe

    cUniversalDLLCalls is BRILLIANT

    Thank You so much

    g8jcf

  15. #55
    New Member
    Join Date
    Feb 2020
    Posts
    2

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Hi all.

    When I'm using DispCallFunc with MSXML DLL (any version) I have noticed that typelib declaration of some methods in this library are not returning VT_HRESULT but VT_OBJECT.

    For example

    DOM.createElement("Root")

    Analysing with typelib information the method createElement gives a vartype of 9 (VT_DISPATCH) for the return value.

    So I suggest to to call DispCallFunc with return vartype 9 but this is not working. I always get the return error &H80020010 of DispCallFunc. Even if I use some modifications of return type, I do not get an error free call of DispCallFunc.

    Obviously using the createElement function returns a IDispatch object reference in VB6.

    So my question is, what are the correct settings for DispCallFunc to call createElement withou any errors?

  16. #56
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Quote Originally Posted by TAPCON View Post
    Analysing with typelib information the method createElement gives a vartype of 9 (VT_DISPATCH) for the return value.
    Here is the relevant IDL from C:\Windows\SysWOW64\msxml6.dll
    Code:
        [
          odl,
          uuid(2933BF81-7B36-11D2-B20E-00C04F983E60),
          hidden,
          dual,
          nonextensible,
          oleautomation
        ]
        interface IXMLDOMDocument : IXMLDOMNode {
            [id(0x00000026), propget, helpstring("node corresponding to the DOCTYPE")]
            HRESULT doctype([out, retval] IXMLDOMDocumentType** documentType);
            [id(0x00000027), propget, helpstring("info on this DOM implementation")]
            HRESULT implementation([out, retval] IXMLDOMImplementation** impl);
            [id(0x00000028), propget, helpstring("the root of the tree")]
            HRESULT documentElement([out, retval] IXMLDOMElement** DOMElement);
            [id(0x00000028), propputref, helpstring("the root of the tree")]
            HRESULT documentElement([in] IXMLDOMElement* DOMElement);
            [id(0x00000029), helpstring("create an Element node")]
            HRESULT createElement(
                            [in] BSTR tagName, 
                            [out, retval] IXMLDOMElement** element);
            . . .
    and apparently createElement *is* returning an HRESULT.

    Quote Originally Posted by TAPCON View Post
    So I suggest to to call DispCallFunc with return vartype 9 but this is not working. I always get the return error &H80020010 of DispCallFunc. Even if I use some modifications of return type, I do not get an error free call of DispCallFunc.

    Obviously using the createElement function returns a IDispatch object reference in VB6.

    So my question is, what are the correct settings for DispCallFunc to call createElement withou any errors?
    You cannot use DispCallFunc API directly as an errorless version of the built-in CallByName, a version that does not raise any errors as returned in the HRESULT. This would require manually calling IDispatch::Invoke as LaVolpe has shown in previous posts here.

    For an errorless direct replacement of the built-in CallByName you can take a look at this DispInvoke function that uses DispCallFunc for the heavy lifting too.

    cheers,
    </wqw>

  17. #57
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    HOW TO BIND A VB FUNCTION in a bas to cdecl dll api?
    i want to use:
    Code:
     Public Declare Function sqlite3_exec Lib "sqlite3"(ByVal sqlite3 As Long, ByVal zSql As String) As Long
    or 
    Function sqlite3_exec_vb Lib "sqlite3"(ByVal sqlite3 As Long, ByVal zSql As String) As Long
    msgbox "ASM CODE"
    end function
    
     Build_CDecl_InVbStdcallFunction  GetProcAddress("sqlite3_exec"),addressof sqlite3_exec_vb,args=2
    
    sub Build_CDecl_InVbStdcallFunction(CdeclApiAddress as long ,VBFunctionAddress,Args as long)
    dim AsmCode() as byte,ByteLen as long 
    ****code here?
    'ByteLen=ByteLen+***
    
      Vblegend.WriteProcessMemory -1, ByVal VBFunctionAddress, AsmCode(0), ByteLen, 0
    end sub
    hao to call Sqlite3.dll with cdecl?-VBForums
    https://www.vbforums.com/showthread....dll-with-cdecl

  18. #58
    Member
    Join Date
    Jul 2017
    Posts
    43

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Hi all,

    I've created an activex DLL and use this class to call functions from a standard DLL (one that I don't own, can't look at the source code). It all works fine however when I call my DLL from an ASP page, it is half a second slower than running it through VB6 (IDE or compiled).

    I've added timing code to the Universal DLL class and it's this line that's slower:

    Code:
        lValue = DispCallFunc(0&, fPtr, CallConvention, FunctionReturnType, _
                             pCount, vParamType(0), vParamPtr(0), vRtn)
    I pass the DLL an XML string. It then runs several queries and returns an XML string. Has anyone got any ideas why it might be slower?


    VB6 program > Calls my activex DLL > Calls standard DLL. Fast, 250ms
    VB6 program compiled > Calls my activex DLL > Calls standard DLL. Fast, 250ms
    ASP page > Calls my activex DLL > Calls standard DLL. Slow, 750ms

    This happens every time. There is no difference in the calls, the same data is being passed from my DLL to the standard DLL in both cases. I can see the same SQL queries are being run and that they take the same amount of time.

    I've tried disabling Windows Defender and that hasn't made a difference.

  19. #59
    Member
    Join Date
    Jul 2017
    Posts
    43

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    I've fixed the issue with ASP slowness but still no idea why. Instead of declaring the object in the global.asa, I moved it to page scope.

    So instead of this in global.asa:

    Code:
    <object runat="server" scope="application" id="specialsDLLWorker" progid="prjSpecialsDLL.clsWorker">
    	specialsDLLWorker = prjSpecialsDLL.clsWorker
    </object>

    I put this in the page:

    Code:
    			Dim specialsDLLWorker
    			Set specialsDLLWorker = Server.CreateObject("prjSpecialsDLL.clsWorker")


    That seemed to fix the issue with slowness. Not ideal as it would make more sense to have this one in a global variable. I was also mucking around with the threading model and apartment is much faster.

    I realise I'm off topic now, but if anyone can point out why global.asa is slower than page scope, please let me know!

  20. #60
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Quote Originally Posted by bahbahbah View Post
    That seemed to fix the issue with slowness. Not ideal as it would make more sense to have this one in a global variable. I was also mucking around with the threading model and apartment is much faster.
    It's common knowledge with Classic ASP to keep global objects (in application state) only free-threading capable instances so that these can be used from MTA (i.e. methods can be called by multiple threads/requests simultaneously).

    VB6 does not support MTA (cannot compile free-threaded components) so you end up with single-threaded component in MTA which *serializes* access to its properties i.e. each request has to wait in line until all other requests finish working with this global instance so that it get a time slot alotted and can call a method of this global instance -- not kosher!

    The same global object problem exists with standard Scripting.Dictionary -- just don't keep instances of these STA components in IIS application state but use IISSample.LookupTable replacement which is a free-threaded component AFAIK.

    cheers,
    </wqw>

  21. #61
    Member
    Join Date
    Jul 2017
    Posts
    43

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Quote Originally Posted by wqweto View Post
    The same global object problem exists with standard Scripting.Dictionary -- just don't keep instances of these STA components in IIS application state but use IISSample.LookupTable replacement which is a free-threaded component AFAIK.

    cheers,
    </wqw>
    Brill, thanks mate. I'll look into the IISSample.LookupTable.

  22. #62
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Quote Originally Posted by jsvenu View Post
    Dear Lavolpe,

    I tried to hide form 2 in standard exe project.It hides if I use tc.hide directly where tc is form2 object.
    But when I try to hide form2 using CallFunction_COM giving 516 as the address of Hide method
    'ie, vtableoffset as per interface _Form which derives from IDispatch located in vb6.olb in vb98 folderwhen we view the typelib using oleview.Hide is the 122th method+3(for IUnknown)+4(for IDispatch)=129*4bytes=516.
    the Hide method of the form2 is not called.

    Can you clarify me where I am doing wrong.
    I am attaching the sample standard exe project.I have used your cUniversalDLLCalls class from prjUniDLLcalls.zip sample.

    regards,
    jsvenu
    Code:
            sName = "Hide" ' << change to another known method in the class

    does it can get more disp id?

    Code:
            Dim vv(2) As Long
            Dim lDispIDList(2) As Long
            Dim S(2) As String
            S(0) = "Caption"
            S(1) = "aa"
            S(2) = "Hide"
            vv(0) = StrPtr(S(0))
            vv(1) = StrPtr(S(1))
            vv(2) = StrPtr(S(2))
        
            Call c.CallFunction_COM(IID_Dispatch, IDispatchIDsOfNames, CR_LONG, CC_STDCALL, VarPtr(aGUID(0)), VarPtr(vv(0)), 1&, 0&, VarPtr(lDispIDList(0)))

    i only use this code can hide form2,but pIndex = DispCallFunc(*)<>0 why?
    i do GetLastDllErr

    do you have a full sample?

    The second similar question, is it possible to write the event callback on the VB6 class object, implement the IUnknown interface, and delete all the redundant interfaces in the class?
    This way I don't have to create a module with each callback and implement the virtual IUnknown interface.
    Last edited by xiaoyao; Jun 6th, 2023 at 01:38 AM.

  23. #63
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Quote Originally Posted by LaVolpe View Post
    Bonnie, if this is a Sub from a VB class you want to call, and you know the method's name, far easier:
    :: Copy pointer to uninitialized object and call the Object.SubName, remove pointer from that object, done

    1) declare a variable vArgs() As Variant, size it to the number of parameters the method expects
    2) populate it in reverse order and ensure the correct vartype of each param, example:
    [indent]method's params: (Index As Integer, NewValue As Long)
    Code:
    Function CallComByMethod(Obj1 As Object, MethodName As String, ParamArray ArgP() As Variant) As Variant
      Const IUnknownRelease As Long = 8&
        Const IDispatchIDsOfNames As Long = 20&
        Const IDispatchInvoke As Long = 24&
        
        Dim IID_Dispatch As Long, lDispID As Long
        Dim aGUID(0 To 3) As Long, sName As String
        Dim DP As DISPPARAMS, vRtn As Variant
        Dim C As New cUniversalDLLCalls
      
        
        sName = "{00020400-0000-0000-C000-000000000046}" ' GUID for IDispatch
        C.CallFunction_DLL "ole32.dll", "IIDFromString", STR_NONE, CR_LONG, CC_STDCALL, StrPtr(sName), VarPtr(aGUID(0))
        ' ensure object implements IDispatch...
        C.CallFunction_COM ObjPtr(Obj1), 0&, CR_LONG, CC_STDCALL, VarPtr(aGUID(0)), VarPtr(IID_Dispatch)
        If IID_Dispatch <> 0& Then
            Erase aGUID()
            Call C.CallFunction_COM(IID_Dispatch, IDispatchIDsOfNames, CR_LONG, CC_STDCALL, VarPtr(aGUID(0)), VarPtr(MethodName), 1&, 0&, VarPtr(lDispID))
            If lDispID > 0 Then
            Dim Arg() As Variant
            Dim i As Long, ub As Long
            ub = UBound(ArgP)
            
            If ub <> -1 Then
            ReDim Arg(ub)
            For i = 0 To ub
                '以相反的顺序填充它并确保每个参数的正确 vartype
                Arg(i) = ArgP(ub - i)
                'Arg(i) = VarPtr(ArgP(ub - i))
            Next
            DP.rgVarg = VarPtr(ArgP(0))
            'DP.rgVarg = VarPtr(Arg(0))
            DP.cArgs = ub + 1
            End If
                Call C.CallFunction_COM(IID_Dispatch, IDispatchInvoke, CR_LONG, CC_STDCALL, lDispID, VarPtr(aGUID(0)), 0&, 1&, VarPtr(DP), VarPtr(vRtn), 0&, 0&)
                Debug.Print "return value if any: "; vRtn
                CallComByMethod = vRtn
            Else
                Debug.Print "method ["; sName; "] not found"
            End If
            ' Release the interface at some point. QueryInterface calls AddRef internally
            C.CallFunction_COM IID_Dispatch, IUnknownRelease, CR_LONG, CC_STDCALL
        End If
    End Function
    , ParamArray ArgP() As Variant
    How about reversing the order of the parameters, because my parameters also return values, so I can't create a variant copy.

Page 2 of 2 FirstFirst 12

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