Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample Code #14

Closed
pdgmdm opened this issue Jun 11, 2018 · 9 comments
Closed

Sample Code #14

pdgmdm opened this issue Jun 11, 2018 · 9 comments
Labels

Comments

@pdgmdm
Copy link

pdgmdm commented Jun 11, 2018

Hi, would it be possible to add some sample projects for macos/Windows ? I would like to create a DS for a webcam...

@xricht17
Copy link
Owner

Hey, I'll see what I can do. Though, I am not sure it will help you that much. TWPP is meant to make your life easier, not to hide TWAIN, you actually have to understand the original API. This applies even more to DS than to APP, as DS is more challenging to implement correctly. Please see TWAIN specification before you attempt any serious work: https://www.twain.org/specification/.

@pdgmdm
Copy link
Author

pdgmdm commented Jun 28, 2018 via email

@xricht17
Copy link
Owner

Hi, I have not forgotten about that sample code I promised you earlier, I hope to put something together next week.


About you question. I would not recommend to use these structures to hold your actual data, use them only to pass information within the TWAIN API. You should consider using them for other purposes only if you need to optimize your code. Otherwise, they will get into your way more often than not.

Capability class, and most other TWPP classes, are designed to be small containers that utilize C++11 move semantics, and to disallow copy semantics. That means you should never use dynamic memory to create them yourself (bad idea in C++ in general), nor should you use pointers to them.


In your example, you create a temporary object with createArray, and then store its address in a map:

caps[CapType::SupportedCaps] = &Capability::createArray<CapType::SupportedCaps>(3);

This will not work. A new object is created in the createArray method, it is move-returned to the caller, the caller takes its address, and discards the object as it is not assigned anywhere. The destructor of the new object is run before you assign your, now useless, pointer to the map. Have a look at std::unique_ptr - TWPP classes should be handled in much the same way.

If you truly need a container to hold Capability objects, the correct way, in case of std::map could be:

Capability cap = Capability::createArray<CapType::SupportedCaps>({CapType::SupportedCaps, CapType::IXResolution, CapType::IXResolution});

std::map<CapType, Capability> caps;
caps.emplace(std::make_pair(CapType::SupportedCaps, std::move(cap)))

This creates a Capability instance with the 3 specified entries, sets it to variable cap, then creates a map between CapType and Capability, and finally moves cap into the map. The content of cap is now inside the map at index 0, and the cap itself is left empty.

Have a look at helper methods in Capability that allow you to create a fully initialized instance in one call, instead of having to assign members yourself as an additional step.


To return a Capability, or just anything except status, you move it into the proper method parameter. In this case, it is the data parameter, that is both input and output parameter. This is the main reason you should not use TWPP to store your data. The data of Capability instance is moved outside your domain, and you are left with an empty container. It is due to the fact that, in TWAIN, application is the endpoint that usually frees-up memory allocated by data source.

@xricht17
Copy link
Owner

Added a sample source in d7bae8b

@pdgmdm
Copy link
Author

pdgmdm commented Jul 16, 2018

Hi,
The sample application is working fine, however when I try to do some testing using apps like "Twister TWAIN Analyser" or "Inspector TWAIN" it does not work correctly.

For the "Inspector TWAIN" I get an SeqError when the app tries to close the DS when a transfer is started.
For the "Twister TWAIN Analyser" the app always crashes after many Get/GetCurrent/GetDefault calls.

Do you have tried this before ?

@xricht17
Copy link
Owner

There still seems to be an issue with old DSM support. I hoped it was resolved in f222721. Obvously it was not. Created issue #15.

@xricht17
Copy link
Owner

Issue with Twister TWAIN Analyser seems to be due to the app passing uninitialized handle to the DS, thus resulting in an attempt to free invalid memory.

@xricht17
Copy link
Owner

Fixed the issue with Twister TWAIN Analyser in 5b2af94. Issue #15 will need more time. I am going to look at it at the weekend.

@xricht17
Copy link
Owner

Fixed the freeze in Inspector Twain (issue #15), the example DS now passes certification with 0 errors.
Twister TWAIN Analyser requires support for setting scan area for some reason. I do not think it is required by the TWAIN specification. Though, I will see what I can do in #17.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants