Exporting c++ function, declared in vb6, getting “remote procedure call failed” runtime error

心已入冬 提交于 2019-12-12 03:02:42

问题


I have a dll written in C++ that is being exported like so:

extern "C" {
    extern _declspec(dllexport) (VOID) Merge(LPCSTR szFileName, LPCSTR szMergeString, DWORD dwAlignment, BOOL fRepeat);
}

That function is defined elsewhere as:

extern _declspec(dllexport) (VOID) Merge(LPCSTR szFileName, LPCSTR szMergeString, DWORD dwAlignment, BOOL fRepeat)
{   
    Tools::Merge(gcnew String(szFileName), gcnew String(szMergeString), dwAlignment, fRepeat == TRUE);
}

In my vb6 dll, I have declared the remote call like this:

Private Declare Sub Merge Lib "Tools.dll" (fileName As String, mergeString As String, Alignment As Long, repeated As Boolean)

Then I call it in the code like this:

Merge strPageFileName, "COPY", 5, True

When I run the app, I get "Automation error: the remote procedure call failed" in a message box.

Tools.dll is in C:\Windows\system32. I tested with a bad dll name, to make sure that wasn't the problem, and get an error saying it could not find the file, so I know that's not it. Anything else I need to do to get this to work?

EDIT: Changing the variable type per xxbbcc's answer below allowed this to function correctly. However, it created a new, so far utterly unsolvable problem. I created another question here that has some of the details about it.

The remote call is happening in a COM+ dll, inside a function that returns type integer to another non-COM dll. For some strange reason, the COM+ dll's function is now returning a variant of type VT_ERROR instead of an integer. I have tested this thoroughly and determined that it does not matter what I do with the return value beforehand, setting it to any value, etc, it always returns an error. The odd part is that the value of the error is apparently 0. I have called CInt(returnValue), CStr(returnValue), and CLng(returnValue), and they return 0, Error 0, and 0, respectively.

I have been unable to find any information explaining why a function that is supposed to return an integer would suddenly be returning an error instead. This is giving me a type mismatch error in the non-COM+ function, as it tries to assign the return to a local integer. Changing that to a variant allowed me to do the casts above. Calling VarType(returnValue) gives 10, which is vbError. We don't want to potentially lose failure information from other calls inside the COM+ dll, so I can't just ignore the return value.


回答1:


BOOL should be defined as Long in VB6 and the value passed for it should be 0 or 1, not boolean values. It should also be ByVal - since parameters are passed by values in C / C++, you must make sure that your VB6 program follows that. Right now your VB6 program passes a pointer to a Boolean, rather than an actual Long. Your strings should also be defined as ByVal.

This article - while dated - has some useful information about why strings should be passed from VB6 as ByVal to C code.

Another thing - I never successfully exported a function to VB6 using declspec(dllexport). I did a lot of C / VB6 coding in the past but the only way it ever worked was through DEF files. I can't explain why (it may have been because of my ignorance). Ignore this part of my answer if fixing the BOOL parameter solves your issue. :)




回答2:


Try declaring the String parameters in your VB6 Declare statement ByVal. Change "filename as String" to "ByVal filename as String", etc.




回答3:


My current solution to this has been to write a tiny c++ console application that calls the exported function, and call the exe from within the vb6 dll.



来源:https://stackoverflow.com/questions/16429119/exporting-c-function-declared-in-vb6-getting-remote-procedure-call-failed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!