We're using Eclipse CDT for C++ 11 code. I have a class I need to refactor so it can be tested. We're using Google Test/Google Mock to write our unit tests. One class contains a Boost socket, like such:
class BoostUser {
...
private:
...
boost::asio::ip::udp::socket theSocket;
....
}
We need to mock calls coming back from the socket, so we decided to change theSocket to a pointer and inject it via the constructor. Since we're using C++ 11, I used a unique_ptr. So our member changed to this:
class BoostUser {
...
private:
...
std::unique_ptr<boost::asio::ip::udp::socket> theSocket = nullptr;
....
}
I changed all the uses of theSocket to use -> instead of .. So calls changed from something like this:
theSocket.open(listenEndpoint.protocol());
to this:
theSocket->open(listenEndpoint.protocol());
I compiled it, it compiled fine with no errors. I already had a few unit tests, and they still worked. I started to change the constructor so it took another parameter, the socket for the dependency injection. And that's when I noticed a peculiarity.
All the instances where I changed the dot . to the arrow -> showed as errors. The Eclipse errors reported "Method '[function_name] could not be found'". It showed them for every instance where I made the changes, but, remember, it compiled with no errors. If these were real errors, I would've gotten compile errors.
As an experiment, I changed the smart pointers to just a raw pointer, like this:
boost::asio::ip::udp::socket* theSocket = nullptr;
And Eclipse was perfectly happy with that. It still compiled fine, and Eclipse didn't show any errors. But since this is C++ 11, we're using unique_ptr all over the place, and Eclipse is perfectly happy with them. It's just in this instance where Eclipse freaks out over smart pointers, and I can't check in code that uses raw pointers.
Has anyone else run across this problem with Eclipse, smart pointers and Boost classes?
Related
I am trying to implement a test_runner for BOOST_TEST that plugs-in to a set of shared_libs containing the tests.
I got the initial sample libs/test/tools/console_test_runner from official boost src. But unfortunately, this code does not compile and is unmaintained.
I have managed to put up a working test_runner, which works fine for first iteration that loads up the shared lib, and executes its testcases.
But if i loadup any other shared lib in the second iteration, the test_runner's behaviour is undefined and crashes.
I have shared the sample code as a gist. I guess, the issue lies with the de-initialization of the boost test framework in the shared code, but i cant seem to figure out why.
The load_library open/close looks fine to me.
gist
As it is written today, Boost.Test expects that only one and unique initialization is performed.
Basically from your Gist, at the end of the bool load_test_lib() call, Boost.Test continues its initialization with the test tree that should have been defined when pulling your shared library symbols.
I believe from there you can load other shared libraries, but before returning from the load_test_lib function.
I am hacking around a problem we've created for ourselves. What I would like to do is log a warning in our TFS builds for any code that is instantiating a specific class. I don't want a run time warning (I've got one in place already), I want a build time warning that ProjectX is using BadClass.cs. The idea being it will give us an additional place to see things that need to be fixed once our hack is no longer needed.
So something like this:
public class BadClass
{}
public class OkClass
{}
public class MyBadService
{
var a = new BadClass(); <-- Logs a warning to the build output
}
public class MyOkService
{
var a = new OkClass(); <-- Does not log a warning
}
Edit:
I do not like the idea of using Obsolete; its a misnomer. We've already got code with Obsolete attributes and this would get lost in the noise. I don't want a generic warning that I can't control the message for. I want bright neon signs with klaxons firing and a thousand exclamation points in the message. Basically everything I can do short of failing the build. I'm using the #warning precompiler directive right now and its mostly doing what I want but it requires a human to remember to add the warning. I'm looking for something more automagic. I've seen third party libraries do stuff like this so I know its possible.
Why not just use the Obsolete attribute? It can generate a build warning for you:
https://learn.microsoft.com/en-us/dotnet/api/system.obsoleteattribute?view=netframework-4.8
You can even make it emit an error too if you want.
The answer could be negative I think.
It seems that you use or call msbuild.exe to build your C# projects. But as far as I know, MSBuild in fact calls csc.exe to build C# projects in build time.
So actually what you want is logging a warning when the compiler compile the C# code if it recognize somewhere in your code uses the BadClass in build time.
If you have the source code of BadClass in the same solution, add a project reference format to the xx.csproj which contains BadClass, and set a #warning in the BadClass it may generate the warning in build time.
But I think the scenario you're in is something like: You developed one Assembly and distribute it to your user, so you want it generates a warning when the user calls one BadClass in your assembly and builds his own project to remind him of taking care when using this bad class. If so, this is impossible for msbuild AFAIK. If I misunderstand anything, feel free to know me know :)
Update:
As Daniel and Johnson said, ObsoleteAttribute is enough to do this. Though no valid way to generate warnings from msbuild aspect directly, but msbuild will call C# compiler during build process, so generates a compiler warning can output to build output window.
I have a body of 'normal' C++ code which I'm trying to make usable by a C# client. I have successfully compiled this with /CLR. I now know that this isn't enough: I have to introduce managed wrapper classes ("ref") to make the code callable from managed code. This question is about what happened before I introduced the ref classes.
I found that the native C++ classes were visible from the C# project, and that I could write
MyNativeClass mnc = new MyNativeClass();
... although any attempt to call a method on the instance was rejected by the compiler. I found that when I ran the C# code, the MyNativeClass constructor was never called - indeed the attempt to instantiate mnc seemed to produce no code at all, so completed without error.
How was C# interpreting the native types in my project? Why did the compiler apparently allow me to instantiate an instance? Why were methods treated differently to the types themselves?
You made two mistakes to make this code work. First is that you declared the C++ class public, like this:
public class MyNativeClass {};
This is not syntax that makes sense in C++ but it is allowed by the C++/CLI compiler. Omitting public would have produced an error message in your C# code, CS0122: "Foo is inaccessible due to its protection level".
Second mistake is that you compiled your native C++ class with /clr in effect. Which works fine, any C++03 compliant code can be compiled to IL and gets just-in-time compiled to machine code by the jitter, just like managed code. And executes fine as well. It is however not efficient to do so, you lost the advantage of having the compile-time optimizer available to produce the best possible code. It still gets optimized, but now by the jitter which doesn't have the same luxury of time available to do as good a job as the C++ code optimizer can do. You avoid this by moving the C++ code in a separate source code file so you can compile it without /clr in effect. Or by using #pragma managed in your source code.
Anyhoo, what you ended up with was an assembly that indeed contains a declaration for MyNativeClass that any managed compiler can see. Something you can see for yourself by running ildasm.exe on the assembly. You'll see that it gets embedded as a value type type. Just a blob of bytes with no constructor and no methods. Which is a decent match for a C++ object from a managed point of view, just bytes that can be stored anywhere a value type can be stored. Declaring a variable of that type in C# works but doesn't do anything useful, it just creates the blob with all bytes set to 0. The only possible use of this declaration is that you can declare a typed pointer to the class and pass it around, that's all.
Apologies in advance for the following verbose question ; I am a COM noob.
Scenario: I need to call a managed DLL built with C# from native Visual C++ code. In my native VC++ code, I do the following after registering "SomeDLL.dll" and generating the "SomeDLL.tlb" file with RegAsm.exe.
Import the TLB file with #import "SomeDLL.tlb"
Use the class MyClass defined in the DLL with CComPtr<MyClass>.
Everything's great! It compiles, and I can run the code etc. It hits the fan when I try to run this application on a different machine (i.e. not the one I compiled it on). I copy all the required DLLs, and I register the same DLL with RegAsm.exe but it doesn't work.
It specifically fails when it tries to initialize the COM library with CoInitialize(0) and returns the S_FALSE error which means
The COM library is already initialized on this thread.
I can confidently state that I have not called this function anywhere else in my code.
Any suggestions?
Hard to help you find that code from here, you're a lot closer. Maybe a DLL that gets injected.
Getting S_FALSE is not an error, getting RPC_E_CHANGED_MODE would be quite bad. Be sure to use the FAILED macro:
HRESULT hr = CoInitialize(0);
if (FAILED(hr)) {
CallNineOneOne(hr);
exit(hr);
}
Maybe you called OleInitialize or another function which calls ComInitialize behind the scenes.
Anyway, it does not matter to call CoInitialize several times per thread if you match each of them with a call to CoUninitialize
I'm currently dealing with a part-time (and annoying) bug with some extension methods in VB .NET (VS 2010 and VS 2008).
I have some client projects that use some extension methods from a "Framework" Project I created for general purpose.
However, sometime, when a try to start the solution, I get a long list of error saying the extension method "is not a member of" target object.
When this happen, I can rebuild the solution without getting any error but if I start the project again, the same error will be raised again.
So far I have 2 workaround
A) Go on the extension method definition, delete the tag, compile (with error), put the tag back.
B) Close Visual Studio et re-open it.
Is there any betterway to handle this problem?
There is an active bug report for this problem at Connect. There's a dire need for a repro, a project with specific steps to let them reproduce the issue in-house. Perhaps you can help, it's what it will take to solve it or recommend a workaround.
EDIT: one late addition to this answer, since I've posted this there have been additional questions that note a problem with the IntelliSense parser behaving different from the compiler. There's an issue with the multi-targeting feature, particularly in VS2010, triggered by the Client Profile option for .NET 4. It is the default for a new project. What goes wrong is adding an assembly reference that requires the full profile, commonly because of a dependency on System.Web. You'll get a warning for that, but that's quickly blown away with a large number of errors. The fix is to change the project's Framework Target from client to full.
I've recently encountered this same issue. My project would Build just fine but if I tried to use the Rebuilt option I would get the error about my extension methods not being found on the objects they were extending.
I have managed to fix this today by including an Import at the top of the classes using the Extension method.
So at the top of the file I actually have
Imports project_name.extension_module
I have no idea why this is required but it fixes the problem in my case. I hope this helps somebody else that has wasted as much time with this as I have!
Liam
A less time consuming work around than the two you listed is to "Rebuild Solution" instead of the normal Build Solution. This has always worked for me whenever I run into this problem.
We have something very similar. Call extensions merhod that extends type A. type is actually an instance of type B that implements interface C. interface C has a method with the same name as extension method.
Interface C declares method Foo
Class B inherits from A implements C
Static Class
Static method Foo (this A)
If A is C
(A as C).Foo
When debugging on the line if A is C it actually calls Foo multiple times and you can step at assembly level and see it indicates it is doing the comparison. The way we demonstrate that the call is happen Foo executes a sql statement and we can see sql profiler executing the code in Foo.
Change A as C to reflection and bug goes away. Or use debugger hidden/step through and bug is masked. Also if you micro-step the sql profiler shows the query is getting called multiple times (before Foo is actually called) for each assembly statement.