I have been researching both the C++ (or Windows API) method for creating a socket, and the .Net method for creating a socket. My concern is whether the same error codes that are available in Windows sockets are also available in the .Net Socket class. I have looked at this page on "Windows Sockets Error Codes" and also this page, which describes the error codes for the .Net Socket class.
After looking at both of the above pages, it seems that the .Net Socket class provides just as much in regards to socket error reporting as the Windows API. I would prefer to use .Net to implement a Socket due to the fact that I feel it would be easier for me as someone who does not have a wide range of knowledge when it comes to C++ and network programming. However, this job requires that I be able to report errors of the same granularity as the Windows API.
I'm trying to be as specific as possible here, but with the information provided, what can you tell me in regards to comparing the two with error codes in mind? With my knowledge, I am thinking that the C# Socket class is just as strong in this aspect as the Windows API.
If you receive a SocketException in .NET the exception has a property called ErrorCode which maps to all of the values you posted in your first link.
So both API's are just as granular in their error reporting. The enum you linked to is just for convince so you don't need to make your own constants for the more popular error codes.
const int WSA_E_NO_MORE= 10110;
const int WSAEACCES = 10013;
void Foo()
{
try
{
//...
}
catch(SocketException ex)
{
// These two lines are equivalent.
//if(ex.ErrorCode == WSAEACCES)
if(ex.ErrorCode == SocketError.AccessDenied)
{
//Do something special for access denied.
}
else if(ex.ErrorCode == WSA_E_NO_MORE)
{
//Do something special with the WSA_E_NO_MORE error code
}
}
}
If you want a easy way to see which enum maps to which error code exactly the reference source shows what native constant each enum represents.
Related
I'm trying to implement a very simple, local, HTTP server for my C++ application — I'm using XCode on macOS. I have to implement it from within a dynamically loaded library rather than the "main" thread of the program. I decided to try using boost::beast since another part of the application uses boost libraries already. I'm trying to implement this example, but within the context of my library, and not as part its main program.
The host application for this library calls on the following function to start a localhost server, but crashes when instantiating "acceptor":
extern "C" BASICEXTERNALOBJECT_API long startLocalhost(TaggedData* argv, long argc, TaggedData * retval) {
try {
string status;
retval->type = kTypeString;
auto const address = net::ip::make_address("127.0.0.1");
unsigned short port = static_cast<unsigned short>(std::atoi("1337"));
net::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, port}}; // <-- crashes on this line
tcp::socket socket{ioc};
http_server(acceptor, socket);
ioc.run();
status = "{'status':'ok', 'message':'localhost server started!'}";
retval->data.string = getNewBuffer(status);
}
catch(std::exception const& e)
{
string status;
//err_msg = "Error: " << e.what() << std::endl;
status = "{'status':'fail', 'message':'Error starting web server'}";
retval->data.string = getNewBuffer(status);
}
return kESErrOK;
}
When stepping through the code, I see that XCode reports an error when the line with tcp::acceptor ... is executed:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x783c0a3e3f22650c)
and is highlighted at the single line of code in a function in scheduler.h:
//Get the concurrency hint that was used to initialize the scheduler.
int concurrency_hint() const
{
return concurrency_hint_; //XCode halts here
}
I'm debating as to whether or not I should include a different C++ web server, like Drogon, instead of boost::beast, but I thought I would post here to see if anybody had any insight as to why the crash is happening in this case.
Update
I found a fix that is a workaround for my particular circumstances, hopefully it can help others running into this issue.
The address to the service_registry::create static factory method resolves correctly when I add ASIO_DECL in front of the methods declaration in asio/detail/service_registry.hpp.
It should look like this:
// Factory function for creating a service instance.
template <typename Service, typename Owner>
ASIO_DECL static execution_context::service* create(void* owner);
By adding ASIO_DECL in front of it, it resolves correctly and the scheduler and kqueue_reactor objects initialize properly avoiding the bad access to concurrency_hint().
In my case I am trying to use non-Boost ASIO inside of a VST3 audio plug-in running in Ableton Live 11 on macOS on an M1 processor. Using the VST3 plug-in in I'm getting this same crash. Using the same plug-in in other DAW applications, such as Reaper, does not cause the crash. It also does not occur for Ableton Live 11 on Windows.
I've got it narrowed down to the following issue:
In asio/detail/impl/service_registry.hpp the following method attempts to return a function pointer address to a create/factory method.
template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
execution_context::service::key key;
init_key<Service>(key, 0);
factory_type factory = &service_registry::create<Service, io_context>;
return *static_cast<Service*>(do_use_service(key, factory, &owner));
}
Specifically, this line: factory_type factory = &service_registry::create<Service, io_context>;
When debugging in Xcode, in the hosts that work, when inspecting
factory, it shows the correct address linking to the service_registry::create<Service, io_context> static method.
However, in Ableton Live 11, it doesn't point to anything - somehow the address to the static method does not resolve correctly. This causes a cascade of issues, ultimately leading up to trying to invoke the factory function pointer in asio/asio/detail/impl/service_registry.ipp in the method service_registry::do_use_service. Since it doesn't point to a proper create method, nothing is created, it results in uninitialized objects, including the scheduler instance.
Therefore, when calling scheduler_.concurrency_hint() in kqueue_reactor.ipp the scheduler is uninitialized, and the EXC_BAD_ACCESS error results.
It's unclear to me why under some host processes, dynamically loading the plug-in cannot resolve the static method address, but others have no problem. In my case I compiled asio.hpp for standalone ASIO into the plug-in directly, there was no linking.
The best guesses I can come up with are
maybe your http_server might start additional threads or even fork. This might cause io_context and friends to be accessed after startLocalhost returned. To explain the crash location appearing to be at the indicated line, I could add the heuristic that something is already off during the destructor for ioc
the only other idea I have is that actually the opening/binding of the acceptor throws, but due to possible incompatibilities of types in the shared module vs the main program, the exception thrown is not actually caught and causes abnormal termination. This might happen more easily if the main program also uses Boost libraries, but a different copy (build/version) of them.
In this case there's a simple thing you can do: split up initialization and use the overloads that take error_code to instead use them.
First of all happy new year to everyone, hope you're doing well!
I'm working on a C++ project in which I need to call a C# DLL I created following the first answer of this post. Once I have the DLL, I need to call it from Qt, so by using dumpcpp and the .tlb file generated by regasm, I managed to get the .cpp and .h files to use my classes. Just as a reference, the namespace of the classes is Wrapper, and the main class is Device with guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}.
Once I have the generated files to use the DLL, if I try to create a Wrapper:: Device instance on Qt, I get the following error:
QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
It doesn't give any more information, so I tried to check if the guid was stored on the system registry (I used the regasm command explained on the previously quoted post, and It said that it was successful, but you never know). Opening Registry editor and searching for the Guid revealed that it's present at: Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15}, which, as far as I know, is the right route for these guids, and it points to the right DLL.
I though It may be due to some kind ActiveQt problem, and as the previously quoted post explained how to use that DLL from VS C++, I decided to give it a try, using this as an another reference. I've finished with this code, which is supposed to create an instance of my Device object
#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
int main()
{
try
{
TESTHR(CoInitialize(0));
Wrapper::IDevicePtr devPtr = nullptr;
TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
}
catch (const _com_error& e)
{
CStringW out;
out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
MessageBoxW(NULL, out, L"Error", MB_OK);
}
CoUninitialize();// Uninitialize COM
std::cout << "Hello World!\n";
}
However, this doesn't work either, the createInstance method throws an exception of Class not registered and HR=80040154. Again, according to Registry editor, the class is registered, so I don't understand the error. I've also tried with devPtr.CreateInstance("Wrapper.Device"), devPtr.CreateInstance("Wrapper::Device") or `devPtr.CreateInstance("Wrapper::CLSID_Device") as the links I posted suggest, but in those cases I get another exception with HR=800401f3 and message Invalid class string.
It doesn't matter whether VS or Qt Creator are opened as administrator or not, I get the exact same error.
I have run out of ideas, and I really need to be able to use that DLL from Qt using the files generated by dumpcpp.
Does any one know what could be happening? It feels quite strange to me.
If your C++ application is 64-bit, that's the answer right there, because your C# component is 32-bit (or MSIL but registered to the 32-bit hive). In situations like these, a simple test using VBScript is always useful.
Write a simple VB Script (test.vbs)
Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)
Now, run this macro 2 ways: with 32-bit and 64-bit versions of VBScript:
32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs
This is assuming your C# component is dispatch compatible. If it's not, then it will still give you differing results that you can use to debug.
Assuming automation/IDispatch compatible, one will work and one won't if you have registered your component correctly.
Have you registered correctly? When I use regasm, I always use the the switches /tlb /codebase when registering the C# component for COM.
Ok, in case someone find the same error, I'll explain the solution I found.
The problem was that in my case, the C# class I developed depended on another 32 bits dll which was not registered on my PC. Once I registered the other dll, everything worked fine.
I don't know why VS kept telling me that the class was not registered when my class itselft was registered, it was one of its dependencies that wasn't registered.
Anyway, I discovered this thanks to Joseph's comments, so thanks a lot for your help.
Apache Thrift is one of the more popular choices for an opensource RPC frameworks (gRPC is also one that gets lot of tracktion since release into the open).
In my setup in c++ Im using a TMultiplexedProcessor. I guess this could be any TProcessor for that matter since Im just interested in printing whatever is sent.
This has a method called:
bool process(std::shared_ptr<protocol::TProtocol> in,
std::shared_ptr<protocol::TProtocol> out,
void* connectionContext) override {
My idea was to override this again, so that I could print the in argument - but how can I write TProtocol to output ? (at a glance, it does not seem straightforward to serialize into a string)
I get a feeling there maybe is some other or an easier method. So my question is how can I dump all messages recieved via thrift (for debugging purpose) ?
There's TProtocolTap and TDebugProtocol.
Usage example can be found in thrift_dump.cpp:
shared_ptr<TProtocol> iprot(new TBinaryProtocol(itrans));
shared_ptr<TProtocol> oprot(
new TDebugProtocol(
shared_ptr<TTransport>(new TBufferedTransport(
shared_ptr<TTransport>(new TFDTransport(STDOUT_FILENO))))));
TProtocolTap tap(iprot, oprot);
std::string name;
TMessageType messageType;
int32_t seqid;
for (;;) {
tap.readMessageBegin(name, messageType, seqid);
tap.skip(T_STRUCT);
tap.readMessageEnd();
}
I have a C++ dll which is a plug-in to ADOBE Acrobat. It needs to talk often ( to and fro) and with a fair amount of complicated data-structures to a WPF process.
Any thoughts of what might be the best way to go . Need something that is a little long term and maintainable, in other words would love some ideas around something that lets both process make what looks like methods calls and some infrastructure piece does the marshaling and dispatch . I've tried Windows messages but ran into some conflict issues on ADOBE, also not really interested in anything that causes the dll to get adobe to load the CLR. Only other things that come to my mind are named pipes or http.
Thanks in Advance
Named pipes could do but you won't get a feeling of just calling functions. Named pipe are quite low-level IPC. Other IPC options are:
Windows RPC, you definitely get a feeling of just calling functions.
What about hosting a COM object in WPF application and calling it from the Adobe plugin?
I would go with COM:
Implement an interface in WPF app
generate a typelib (e.g by using regasm)
import the typelib into C++ dll
communicate
if you need bidirectional communication, C++ dll can also implement a COM interface which is then accessed from WPF application.
This is what I have used to connect legacy C++ app with new .NET service, and it works great. The biggest issue is to find people who know COM, but fortunately this doesn't require a deep understanding of COM.
your hint with COM is very intersting. I tried to implement this concept.
I have created an interface in my WPF CallDllFromWpf3Interface project:
using System.Runtime.InteropServices;
namespace CallDllFromWpf3Interface
{
[Guid("F6E0E2E8-CCC6-487B-8BF1-261265061E6A")]
public interface SetValueInterface
{
void SetValue(int value);
}
}
Then I have generated the typelib with the regasm tool:
regasm CallDllFromWpf3Interface.exe /tlb
With the "oleview" tool I can see the typelib and the interface.
The next step was to create a c++ dll project called "CallSetValueInterface".
In my CallSetValueInterface.cpp file I wrote this lines:
#import "D:\Thomas\Programming\WPF\Basics\CallDllFromWpf\CallDllFromWpf3Interface\CallDllFromWpf3Interface\bin\Debug\CallDllFromWpf3Interface.tlb"
void
CallSetValueInterface::startAcq(void)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CallDllFromWpf3Interface::SetValueInterfacePtr Svip("f6e0e2e8-ccc6-487b-8bf1-261265061e6a");
Svip->SetValue(55);
Svip = NULL;
CoUninitialize();
}
After a successful build of the dll project I copied "CallSetValueInterface.dll" to the "CallDllFromWpf3Interface" project.
Finally I changed my WPF code to:
#region SetValueInterface Members
public void SetValue(int value)
{
MyValue = value;
}
#endregion
[DllImport("CallSetValueInterface.dll", EntryPoint = "startAcq", ExactSpelling = true, SetLastError = true)]
public static extern void StartAcqFromDll();
private void Button_Click(object sender, RoutedEventArgs e)
{
StartAcqFromDll();
}
And when the debugger came to StartAcqFromDll() there occurred an error dialog "An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in CallDllFromWpf3Interface.exe".
Does anybody know whats going wrong?
Regards,
ThomasL.
I'm designing an interface that can be used to report errors in C++. (I'm working with a legacy system where exceptions are out of question.) In my youthful naivety, I started along these lines while designing my API:
bool DoStuff(int amount, string* error);
Return value signals success/failure, while error is used to report a human readable explanation. So far so good. Subroutine calls passed along the error pointer and everything was hunky-dory.
I ran into the following problems with this design (so far):
Cannot report warnings.
Not thread-safe.
Next, I decided to go with the following interface, instead of plain string:
class Issues {
public:
void Error(const string& message);
void Warning(const string& message);
void Merge(const Issues& issues);
}
So that I can change my API like this:
bool DoStuff(int amount, Issues* issues);
I'm wondering, is there a more generic/standard API out there that deals with this problem? If yes, I'd like to take a look.
UPDATE: I'm not looking for a logging library. For those who are curious, imagine you're writing a query engine that includes a compiler. The compiler issues warnings and errors, and those need to be returned to the user, as part of the response. Logging has its place in the design, but this is not it.
I usually use things like boost::signals or .NET delegates to report errors/warning/logging/whatever. You report errors with no changes to the interface, and the library user plugs whatever she wants to the signal to get the error reports (writing to a file, updating a console window, aborting the program, throwing an exception, ignoring warnings, etc).
Something like this, at eg. global scope:
boost::signal<void(std::string const&)> logError;
boost::signal<void(std::string const&)> logWarning;
and then
void routineWhichMayFail()
{
...
if (answer != 42)
{
logError("Universal error");
return;
}
}
and you connect something to logError and logWarning at initialization:
void robustErrorHandler(std::string const& msg)
{
std::cerr << "Error: " << msg << "\n";
std::exit(EXIT_FAILURE);
}
void initializeMyProgram()
{
logError.connect(&robustErrorHandler);
}
You can even throw exceptions in the error handler instead of exiting, and use fancier things than bare functions (logging classes, "delegates" -- pointers to methods with a this object bundled, RPC to a distant server). This way, you decouple the error handling from error reporting, which is good. You can also report to multiple destinations, you can even have your handlers return a boolean telling whether the action should be eg. retried.
From your explanation it sounds like you are trying to implement a logging library for your project. You can look at log4cpp or Boost.Log.