Please help! C++ DLL does not call my function in C10 DLL

Hi all,

I need urgent help please.

I have a DLL “rtfconv.dll”, developed in Microsoft Visual C++ 6.0, which calls a Clarion function “CL_ReadRecord” in a Clarion DLL “readrec.dll”. This works OK in our Clarion 6.3 application (and in the past Clarion 5).

rtfconv.dll = Microsoft Visual C++ 6.0
readrec.dll = Clarion

I have converted the Clarion 6.3 application to Clarion 10, so I have a Clarion 10 version of readrec.dll with the CL_ReadRecord function in it. But now the Visual C++ DLL “rtfconv.dll” doesn’t call the Clarion function CL_ReadRecord anymore. The Visual C++ code hasn’t changed, it’s still the same DLL of ages ago. So only the Clarion 6.3 DLL has been converted to Clarion 10 with the same code.

C++ rtfconv.dll -> call to Clarion 5 dll function CL_ReadRecord = OK
C++ rtfconv.dll -> call to Clarion 6.3 dll function CL_ReadRecord = OK
C++ rtfconv.dll -> call to Clarion 10 dll function CL_ReadRecord = NOTHING HAPPENS!

In the Clarion function CL_ReadRecord I have set a MESSAGE which is shown correctly when my C++ rtfconv.dll calls the function in my Clarion 5/6.3 application.
But it IS NOT shown when my C++ rtfconv.dll calls the function CL_ReadRecord of my Clarion 10 application.

This C++ DLL has been developed 20 years ago by another developer in Microsoft Visual C++ 6.0. In a Win32 Windows 10 VM, I have Microsoft Visual C++ 6.0 running and I also have the source code and I am able to compile a C++ rtfconv.dll file. But my knowledge of C++ is zero.

This is a huge problem, because this C++ DLL is the most important part of our application. It also took a lot of time to convert from C6.3 to C10. And now this has become a showstopper.

I have attached a part of the C++ code (RtfDoc.cpp) in which the Clarion function “CL_ReadRecord” is declared/called?
I have also attached the Clarion code (readrec002.clw) of the function “CL_ReadRecord” which is declared as:
CL_ReadRecord( <*CSTRING> , <*CSTRING> , <*CSTRING> , <*CSTRING > , <*CSTRING >),C,LONG, NAME('CL_ReadRecord')

So I don’t understand why the call from the C++ DLL to my Clarion function CL_ReadRecord does not work when the Clarion DLL is compiled under Clarion 10.

I hope that some C++ guru can help me to solve this problem. Any help is appreciated, thank you very much!

Best regards
Jeffrey

some-source.zip (35,6 KB)

Your source is missing too much.

All we can see is a function without data types.
As an aside: do yourself a favor and start using the same code for the declaration and the definition, where you have both the data type and the parameter label.

I can’t tell if you’re exporting the function (look at your .EXP)
And also use a tool like LibMaker to look at your clarion dll to see what is exported.

BTW, you’re passing CSTRING which can be stored CLIP()'d so you should NOT need to re-clip them in your MESSAGE

As a side note, for calling from C++ into CW I use the technique described in the clarionMag article titled “Interfacing with Interfaces” where a shared INTERFACE is built in both C++ and CW and then you can all either way.

I can’t seem to find “Interfacing with Interfaces” by Gordon J Smith
FYI the now outdated URL was http://www.clarionmag.com/cmag/v4/v4n01interfacevc2.html

Run the debugger, set breakpoint in CL_ReadRecord (ideally on first local variable declaration) and see does the control come into this function. If it does then you can try calling AttachThreadToClarion in CL_ReadRecord as first line just after CODE statement.

Instead of Message simpler would be to call OutputDebugString(). Keep the code very simple.

Hello CString('in CL_ReadRecord')
   Code
   OutputDebugString(hello)

Since your parameters are all CSTRING you can add additional lines to output those.

I’d open your C++ DLL in Dependency Walker and see what’s getting loaded. I would Not want it loading both the 6.3 and 10 RTL DLLs. It may not be linking what you think, Depends will show you.

1 Like

Hi Mark,

Yes, the function is visible in the .EXP and also in LibMaker.
I opened the C6.3 app in Clarion 10, so the C10 version contains the same code as the C6.3 version.

Best regards
Jeffrey

Are you using a NAME attribute, or relying on Name Mangling.
Can you please show your prototype…

I doubt this is the case,
but I suppose it’s possible that the Name Mangling changed from C6.3 to C10

I’ve always called first from CW into C++
Which required creating an OMF .LIB from the C++ DLL, as it creates a COFF .LIB

Do you need to do something similar going the other direction?
IOW, do you have an out of date COFF .LIB for your Clarion.DLL ?

I don’t know exactly what you mean, sorry for that.
But I attached the Clarion code (readrec002.clw) of the function “CL_ReadRecord” which is declared as:
CL_ReadRecord( <*CSTRING> , <*CSTRING> , <*CSTRING> , <*CSTRING > , <*CSTRING >),C,LONG, NAME('CL_ReadRecord')
which use a NAME attribute.

I don’t know anything about the OMF / COFF part.

I’m sorry, you did show the prototype in your oringal posting, even though you didn’t include it in the attached code.

visual c++ - What’s the difference between the OMF and COFF format? - Stack Overflow

Clarion uses OMF
Microsoft uses COFF

Mark,

Links for Gordon’s articles:

https://clarionmag.jira.com/wiki/pages/viewpageattachments.action?pageId=399456&preview=/399456/401765/cmag-2002-01.pdf

https://clarionmag.jira.com/wiki/download/attachments/399456/cmag-2002-01.zip?api=v2

1 Like

Thank you all for your answers, I highly appreciate your help!! I will look further after the weekend.

Just an additional note, to be more clear:

From my Clarion 10 (v12799) application I first call a function in my C++ DLL (rtfconv.dll) which is executed without any problem. Then, this C++ DLL is calling the Clarion function “CL_ReadRecord” in the Clarion DLL (readrec.dll), but nothing happens (CL_ReadRecord is not executed) when readrec.app has been compiled in Clarion 10. When readrec.app has been compiled in Clarion 5 or 6.3, my C++ DLL is calling the Clarion function “CL_ReadRecord” in the Clarion DLL (readrec.dll) without any problem.

Best regards
Jeffrey

Nothing happens not equals to not executed, run the debugger and see doesn’t it really executed.

Hi Mike,

Thank you, I will try running the C10 debugger after the weekend when I’m back at the office. I have never done something with a Clarion debugger. Is there some article to help me how to run this thing?

Best regards
Jeffrey

F1, search for “debugger”.

Thanks Mike!
I have a multi DLL application. Do you know if it’s sufficient to only compile the one app file with the CL_ReadRecord function in it? I don’t see this info in the help.

Best regards
Jeffrey

Obviously it is. . .

What is Link Mode set to for the app?

Hi Leonid,

DLL(dll_mode)
Is that what you mean?

Best regards
Jeffrey

app properties:
image

Open your C++ DLL in Dependency Walker to show if and what Clarion DLLs it is loading, post a capture here.

The original from an MS developer

https://www.dependencywalker.com/

The above sometimes hangs, this one is newer

Also suggest in Clarion add a very simple export function for C++ DLL to call. No parameters and just do an OutputDebugString. That does mean changes in C++.

CL_Hello(),C,NAME('CL_Hello')
Hello CString('in CL_Hello')
   Code
   OutputDebugString(hello)
   RETURN
1 Like

In my experience, this stuff is often loaded on the fly rather than linked.