edimetia3d / OPC-Client-X64

An open source OPC DA Client SDK/ToolKit written in C++, support both 32 bit and 64 bit.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

not reading/writing items on 64 bit version

aljo666 opened this issue · comments

the problem I think is that 64 bit system uses 64 bit pointers so the items are not correctly addressed
COPCItem * item = (COPCItem *)itemState[i].hClient;
COPCItem pointer size is 64 bit but hClient is DWORD or 32 bit
something similar is for
CTransaction & trans = *(CTransaction *)Transid;
do you already have any solution for this?

Sorry, I don't have this problem. I have used this project in two products, either win32 and x64 works for me fine.
Did you test your code with MatrikonOPC Simulation Server? I'm pretty sure that the Demo works with the simulation server.

Yes I used Matricon simulator. I tested it with Windows 10 64 bit and visual studio 2015. The connection to the OPC server is OK but when it tries to read the data the application crashes. So I did a little change just to test sync read and if I replace COPCItem * item = (COPCItem *)itemState[i].hClient; with a simple search function in which I compare all (DWORD)COPCItems with itemState[i].hClient the read works. Something like
COPCItem * item = getCOPCItem(itemState[i].hClient);

COPCItem *COPCGroup::getCOPCItem(DWORD id)
{
for (int i = 0; i < items.size(); i++)
if ((DWORD)items[i] == hClient)
return items[i];
return NULL;
}
Maybe you have luck and the used memory was only in lower 4 bytes and the DWORD cast was OK. I sort of solved this for sync read but I still don't have any idea on howto solve the async one. Do you think that I'm doing something wrong and it should work also for me? I think that we should use some sort of pair table in which one pair is DWORD and the other is the actual pointer address. However if I compile the app for 32 bit it works ok.

I don't know if changing pointer type will solve the problem because from what I understood on 64 bit systems the pointer addresses are 8 bytes (64 bits) and on 32 are 4 bytes (32 bits) and cannot be changed. I think you should map items with DWORDs to make it work on 64 bit systems. However you can try first with VS2015 to see if it is working for you.

I tested the project with VS2017, this problem occured too. Now I have understood what you said.

  1. the behavior of new is different in VS2010 and VS2017, so i didn't meet this bug before.
    • in VS2010, new COPCItemwill return a pointer at lower memory space, the returned adress is basicly less than 2^32, so 64bit pointer is compatible with 32bit pointer in most situation.
    • in VS2012 or later, Set "Project Property -> Linker -> CommandLine", add /HIGHENTROPYVA:NO , now you can get the same behavior like VS2010, so the problem should be solved in most situation.
  2. I just shared my work on this project, and I am not focusing on it now. I will try to fix it if I have time. Now I can only update the readme.
  3. Here are some tentative suggestions if you want to fix it
    • you can write a customed allocator to replace default new
    • I think the project should work if you can retrieve the original pointer.
      • It is easy to retrieve pointer when sync read/write.
      • When async read/write, you can search// TODO this is bad - server could corrupt address - need to use look up table,there, as original develpoer adviced, you can build a new map to retrieve the original pointer from clienthandles[i]/Transid

Thanks for your reporting.

Thank you, I have the same problem.I looked for it for a long time, and finally found it in detail here

Hi, I'm using VS2017 and I do not see the "Linker" item in the project properties.

Anyway, am I wrong thinking that the 64 to 32 bit casting will be solved using the proper conversion functions as explained for example here?

I raised the warning level to W4, and corrected the truncation warnings using the suggested functions.
So, e.g., given a
CTransaction * trans
casting to a DWORD won't be
(DWORD)trans
but
PtrToUlong(trans)

What do you think?

Did the fixed cast solve the async read/write issue in your project?

No, the /HIGHENTROPYVA:NO option did.

I've fixed the issues and implemented a map for storing the CTransaction pointers as described in the comments. Can I upload a patch somehow or do I have to create a pull requst?

Hi guys, am using your OPC-Client SDK since about 10 years as part of our own software package for industrial controls, so I already know it quite well. Recently I also had to port our software to 64-bit, and came across similar issues as you've been facing. So after I've found out you're also working on this I just took your latest version from git (via git clone) and adapted it to my current software, and then fixed it, in the right way, so no "/HIGHENTROPYVA:NO" or alike, but all with a new transactions map, and by extending the already existing items map. Which means now handles are really handles, and not addresses anymore. Am using Qt as toolchain, and now your SDK compiles and runs properly under 32 and 64 bit, and with or without UNICODE. And both Qt5 and Qt6, and from on msvc2010 until msvc2019. Am using cmake instead of qmake, so I didn't care much about it. Am also using your SDK as one of about 10 libraries, fixed the Microsoft declarations etc., but else exactly with the revamped project you've provided. So in case anybody is interested, here is a Dropbox link to a .7z with my whole SDK folder: https://www.dropbox.com/s/uc9a8p6cnej0jqs/OPC-Client-X64.7z?dl=0

@wgr-vremsoft

Thanks for your works, it looks pretty exciting.

Would you mind making a github pull request too?

If the github workflow bothered you, you may leave a public email address here, It will be my pleasure to create a new commit in your name.

@edimetia3d

thanks for your reply, and your guess is right, am not really familiar with git, we're using svn, so I only know how to git clone ;-)

so of course it would appreciate if you could do so, it's wolfgang.griech@gmail.com