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.

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

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

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

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