HydrogenAudio

Hosted Forums => foobar2000 => Development - (fb2k) => Topic started by: jonpb on 2013-03-17 04:07:06

Title: C++/CLI component
Post by: jonpb on 2013-03-17 04:07:06
Hi,
My goal is to write a WCF service to expose playback_control and playlist_manager in order write a winrt player using foobar2000 as the backend. This requires a C++ to .NET bridge. I was hoping to use a combination of reverse p/invoke and C++/CLI aggregation/composition to accomplish this.

The inititquit implementation is straight up inheritance coupled with initquit_factory_t. This works fine with reverse p/invoke.

I'm puzzled with the playback_control implementation which seems to use composition on the C++ side via static_api_ptr_t<playback_control>. This should not be a problem to then use composition on the C++/CLI side except for the fact that when I include foobar2000.h in a .cpp compilation unit compiling with the /clr switch I get the following errors:

Before initguit::on_init
First-chance exception at 0x75204b32 in foobar2000.exe: Microsoft C++ exception: foobar2000_io::exception_io_data_truncation at memory location 0x0031e91c.
First-chance exception at 0x75204b32 in foobar2000.exe: Microsoft C++ exception: foobar2000_io::exception_io_not_found at memory location 0x0031e940.
First-chance exception at 0x75204b32 in foobar2000.exe: Microsoft C++ exception: foobar2000_io::exception_io_not_found at memory location 0x0031e940.

initguit::on_init gets called and everytings seems ok, then I close the application

On exit of the application:
First-chance exception at 0x75204b32 in foobar2000.exe: 0xC0020001: The string binding is invalid.
Unhandled exception at 0x75204b32 in foobar2000.exe: 0xC0020001: The string binding is invalid.

And it crashes Visual Studio bad, I have to restart the IDE.

Any ideas to solve this? Am I using playback_control correctly? I created a C++ wrapper class which just forwards each function call to the aggregate member static_api_ptr_t<playback_control>.

EDIT: Just to clarify, I need to declare wcf service class objects in the on_init implementation and unfortunately wcf requires instantiable objects in these methods, interfaces are not allowed, thus the problem of requiring to #include foobar2000.h in the /clr compilation unit which implements the service. If I can use the "factory" paradigm for playback_control like is used for initquit perhaps I can use reverse p/invoke for these interfaces?

Thanks.
Title: C++/CLI component
Post by: jonpb on 2013-03-19 05:00:43
C++/CLI requires linking to Multithreaded DLL crt, so I had to compile the shared libs thus. Is this supported?

Also, probably not an issue, but just curious, the readme file says:
"shared.dll (various helper code, mainly win32 function wrappers taking UTF-8 strings)"
why does shared.dll use UTF-8 strings when Windows internally uses UTF-16.
Title: C++/CLI component
Post by: foosion on 2013-03-21 00:03:40
C++/CLI requires linking to Multithreaded DLL crt, so I had to compile the shared libs thus. Is this supported?
Yes, it is. The default settings use the static-linked runtime to simplify the distribution of components.

why does shared.dll use UTF-8 strings when Windows internally uses UTF-16.
foobar2000 has used UTF-8 internally for as long as I can remember, i.e. at least since version 0.4.2. The 0.4.x series added compatibility with Windows 98 while older versions worked exclusively under NT based versions of Windows. So shared.dll was part of the Unicode/ANSI abstraction layer.
Title: C++/CLI component
Post by: jonpb on 2013-03-29 07:12:45
Thanks Foosion.

Most of my first post was a confusion of how static_api_ptr_t<> works... static_api_ptr_t<> allows for the isolation required.

I managed to get a wcf client to call into a service hosted by Foobar2000.

The problem now is that the following function, compiled in a C++ compilation unit, throws an SEH exception back to the .net client, i.e. it is not handled.

My guess is that it is a thread issue. Is playback an I/O function that requires being called on the main thread? If so, any ideas on how to do that?

Code: [Select]
void abc_playback_manager::Play() 
{
    static_api_ptr_t<playback_control> pbc;
    try
    {
        pbc->start(playback_control::track_command_play);
    }
    catch(pfc::exception const&  ex)
    {
        assert(false);
    }
}


Title: C++/CLI component
Post by: kerpondile on 2013-03-29 10:08:09
See main_thread_callback_manager for queueing commands to run in main thread
http://foosion.foobar2000.org/doxygen/late...k__manager.html (http://foosion.foobar2000.org/doxygen/latest/classmain__thread__callback__manager.html)
Title: C++/CLI component
Post by: foosion on 2013-03-29 11:38:05
My guess is that it is a thread issue. Is playback an I/O function that requires being called on the main thread? If so, any ideas on how to do that?
That is right. See the detailed description of the playback_control (http://foosion.foobar2000.org/doxygen/latest/classplayback__control.html) class. There you will also find a reference to the main_thread_callback that kerpondile has pointed out.
Title: C++/CLI component
Post by: jonpb on 2013-03-30 00:41:30
Awesome, I had no idea you had compiled a doxygen help system. Thanks again Foosion.