C #: Pass the global delegate object to C ++ for callback.

Source: Internet
Author: User

A c ++ DLL is a remote call function component of the company. For a long time, this dll has only three external operation interfaces. From a reasonable point of view, this dll should provide some callback interfaces or events to notify the outer application when the call status changes passively.Program. However, banks have a lot of rules and cannot use ActiveX. Callback is not so stable, especially when interacting with C. That's why I used it all the time.

Until recently, developers of the outer application complained about the DLL. Therefore, I decided to add callback support to this DLL. Although it cannot be determined where the previously used callback is unstable, however, both the existing materials and the tests independently written by myself indicate that the callback passed by C # To C ++ can work normally. Therefore, it must be something wrong with this DLL before it becomes unstable. If it is a big deal to take a weekend, it should always be able to solve it.

Generally, there are two main points for implementing callback:

1. the keyword winapi or call should be added to the callback to declare its call method;

2. Note that the parameter type, especially the length, must be consistent in the C ++ and C # statements. Avoid using pointers and reference types.

Since it has been tested separately before, it is difficult to practice in the DLL. It took a day to modify the program as required. In order to avoid encountering the devil of the legendary man who lives in the maze. In the meantime, we also took a few needles. when defining the callback, we first excluded any character parameters and used only integers. Then we removed the previous intermediate DLL. The original core DLL is the MFC extended dynamic link library, which cannot be directly used in C #. Therefore, a formal DLL is provided outside. Although indirect calling of DLL is normal, making the structure simpler has no harm.

Everything is right, start debugging, get rid of a few small issues, and find that the program is running properly, and the callback output is displayed on the screen happily. I tested all kinds of environments several times, but I am still OK. It seems I am lucky this time. Next, package, write the interface and callback instructions, and draw the status chart.

Before sending it out, I changed some debugging and log information, and then tested it nervously. It turns out to be a regrettable and fortunate action. This is because we met Demon, the demo dude. Well, what's a bad word .....

Fortunately, I have always been enlightened by the fight in my life, and I have never been so self-satisfied before. Yes, but come on. We have two days to back up on weekends. You can't believe it.

Let's see what demon said: system. Windows. Forms. Ni. dll 0xc0000005 access violation.

It's easy to understand.

Check the DLL program first. There should be no problem. All Callbacks are triggered on the main thread, and it should have nothing to do with the thread.

Then determine whether it is C ++ DLL or C # exe. Compile the DLL and exe under debug and release, and then run them in combination, this exception occurs only when the release program of EXE is used. Then, it should be a problem with the C # program.

This is just a very simple example.CodeWhat problems may occur. Debug is normal and release is abnormal. Try to change the compilation option first, and turn off the optimze code. The problem is still the case; then define DEBUG constant is enabled, which is exactly the same as that of the debug version. It seems that this cannot be done.

Check if Google has encountered such a problem. I searched what demon said and found no relevant information... It seems that this is a headache.

Suddenly it seems that the DLL and exe combination tests just now seem to have had an unusual prompt. You can find it again and find that the debug version DLL and the release version EXE run together with the following prompt:

File: i386 \ chkesp. c
Line: 42

The value of ESP was not properly saved stored ss a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

 

Search again. This time, there are quite a few people who are equally unfortunate, but just like the sentence, "Unfortunately people have their own misfortunes ", they seem to have nothing to do with my situation.

I am not looking for help now. I will ask for Baidu to see what happens to C ++ callback code. As a result, I tried several keywords and got nothing. Just as I felt like a big pear, suddenly, I found a interesting post with the keyword "C ++ C # callback delegate" C # handle C ++ library callback error _ unmanaged code transfer delegate is garbage collection, although this old man did not explain anything, the exception content posted here is very special:

Callbackoncollecteddelegate Detected
Message: For "hbvideoparser! Videocomm. Video. HB. hbsdk + srcdataparsecbhandler: invoke "-type garbage collection delegate for callback. This may cause application crash, damage, and data loss. When delivering delegates to unmanaged code, managed applications must keep these delegates active until you are sure they will not be called again.

 

The delegate object passed to C ++ is returned to garbage collection, causing an exception in callback? It seems a little strange, but it's just a dead horse. Modify the demo, upload a global delegate object to the DLL, and then test ~ Haha, the callback output is cheerful again ~

It seems that this is really the case. Check again, change back to the original method of passing the temporary object, add an exception capture in the demo main function, and find that the exception will be passed here, the content is "object reference not set to an instance of an object ". Although not consistent with the above, it should be the same thing.

Now, it's hard to understand. In C #, the reference count is used to determine whether the object can be recycled. In the demo, the created temporary delegate object is only temporarily used and has no reference, although saved in C ++ DLL, it is no longer within the scope of the demo. Therefore, garbage collection is normal.

I thought that the test I wrote alone did not seem to have found such a problem. Why? Is it because the program occupies too little space to perform garbage collection? Click the call button to open it. As a result, the program is abnormal after 30 or 40 pieces of information are output.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.