From d95d305734fbca4a13bb0c209035567bf4a85298 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Fri, 19 Jul 2024 03:59:19 -0400 Subject: [PATCH] more binding fuckery i'm going to switch the build to clang-cl. To test, I've added EXE build support back to the speech2 C++ buildsystem and I'm going to replace the current mingw command lines for clang-cl in the next commit. Because we only need XP SP3 compatibility, we won't need any compat library stuff, but I may still alter his libc++ fork if MSVC CRT ends up blowing too many chunks. --- Justfile | 2 +- SAPIServer/SpeechDLL.cs | 10 ++++++---- speech2/Makefile | 27 +++++++++------------------ speech2/build/configs.mk | 24 +++++++++++++++++++----- speech2/build/rules.mk | 31 +++++++++++++++++++++++++++++-- speech2/src/bindings.cpp | 5 ++++- speech2/src/sapi4/api_sapi4.cpp | 15 ++++++++++----- 7 files changed, 78 insertions(+), 36 deletions(-) diff --git a/Justfile b/Justfile index 2550619..c065885 100644 --- a/Justfile +++ b/Justfile @@ -1,6 +1,6 @@ build: dotnet build -c Release - make -C speech2 -j$(nproc) + make -C speech2 CONFIG=Release -j$(nproc) cp speech2/bin/x86/Release/speech2.dll SAPIServer/bin/Release/net40/windows-x86 cp /usr/i686-w64-mingw32/bin/libgcc_s_dw2-1.dll SAPIServer/bin/Release/net40/windows-x86/ diff --git a/SAPIServer/SpeechDLL.cs b/SAPIServer/SpeechDLL.cs index 39465bb..a1df34b 100644 --- a/SAPIServer/SpeechDLL.cs +++ b/SAPIServer/SpeechDLL.cs @@ -36,16 +36,18 @@ namespace SAPIServer { // Speech2 DLL API. Sync with c++ code. internal class SpeechDLL { - [DllImport("speech2.dll")] + private const string Speech2DLL = "speech2.dll"; + + [DllImport(Speech2DLL, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr speech2_create_api(EngineType type); - [DllImport("speech2.dll")] + [DllImport(Speech2DLL, CallingConvention = CallingConvention.Cdecl)] public static extern void speech2_destroy_api(IntPtr pAPI); - [DllImport("speech2.dll")] + [DllImport(Speech2DLL, CallingConvention = CallingConvention.Cdecl)] public static extern int speech2_api_get_voiceinfo_count(IntPtr pAPI); - [DllImport("speech2.dll")] + [DllImport(Speech2DLL, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr speech2_api_get_voiceinfo_index(IntPtr pAPI, int index); } diff --git a/speech2/Makefile b/speech2/Makefile index 346e722..b64529d 100644 --- a/speech2/Makefile +++ b/speech2/Makefile @@ -2,35 +2,26 @@ include build/arch.mk include build/configs.mk NAME = speech2 - -BINDIR = bin/$(ARCH)/$(CONFIG) -OBJDIR = obj/$(ARCH)/$(CONFIG) +TYPE = dll # Any C++ file in src/ is automatically picked up. CXXSRCS = $(wildcard src/*.cpp) $(wildcard src/*/*.cpp) -VPATH = $(dir $(CXXSRCS)) -OBJS = $(addprefix $(OBJDIR)/,$(notdir $(CXXSRCS:.cpp=.o))) -.PHONY: all dumpinfo clean matrix - -all: $(BINDIR)/$(NAME).dll - -# dir rules -$(BINDIR)/: - echo -e "\e[95mMKDIR $@\e[0m" - mkdir -p $(BINDIR) - -$(OBJDIR)/: - echo -e "\e[95mMKDIR $@\e[0m" - mkdir -p $(OBJDIR) +.PHONY: all clean matrix include build/rules.mk +all: $(BUILD_PRODUCT) + clean: echo -e "\e[91mCleaning... \e[0m" rm -rf $(BINDIR)/ $(OBJS) +# A fun make trick. This allows for verbose compilation if desired. +# Set V=1 or anything, and it'll be verbose. $V.SILENT: -# Include dependency files. +# Include dependency files generated by compilation. +# `make clean` keeps them so we can reuse, however they can +# still optionally be blown away. -include $(OBJS:.o=.d) diff --git a/speech2/build/configs.mk b/speech2/build/configs.mk index e793758..76da831 100644 --- a/speech2/build/configs.mk +++ b/speech2/build/configs.mk @@ -1,11 +1,21 @@ # Base compiler flags. Only change if you *explicitly* know what you're doing. -BASE_CCFLAGS = -MMD -fvisibility=hidden -std=gnu17 -fpermissive -fno-pic -fno-pie -fno-ident -msse -Iinclude -Isrc -D_UCRT -D_WIN32_WINNT=0x0501 -BASE_CXXFLAGS = -MMD -fvisibility=hidden -std=c++20 -fpermissive -fno-pic -fno-pie -fno-ident -msse -Iinclude -Isrc -Ithird_party -D_UCRT -D_WIN32_WINNT=0x0501 -BASE_LDFLAGS = -Wl,--subsystem=windows -fvisibility=hidden -shared -lkernel32 -lshell32 -luser32 -luuid -lole32 + +#ifeq ($(VCDIR),) +#$(error Please set VCDIR in your environment to ) +#endif + + +# _UCRT define forces mingw not to define its stupid wrappers. +BASE_FLAGS = -MMD -fvisibility=hidden -fpermissive -fno-pic -fno-pie -fno-ident -msse -Iinclude -Isrc -Ithird_party -D_UCRT -D_WIN32_WINNT=0x0501 + +BASE_CCFLAGS = $(BASE_FLAGS) -std=gnu17 +BASE_CXXFLAGS = $(BASE_FLAGS) -std=c++20 +BASE_LDFLAGS_SHARED = -Wl,--subsystem=windows -fvisibility=hidden -shared +BASE_LDFLAGS = -lkernel32 -lshell32 -luser32 -luuid -lole32 Release_Valid = yes -Release_CCFLAGS = -O3 -ffast-math -fomit-frame-pointer -DNDEBUG -Release_CXXFLAGS = -O3 -ffast-math -fomit-frame-pointer -DNDEBUG +Release_CCFLAGS = -O3 -DNDEBUG +Release_CXXFLAGS = -O3 -DNDEBUG Release_LDFLAGS = -s Debug_Valid = yes @@ -21,3 +31,7 @@ endif ifneq ($($(CONFIG)_Valid),yes) $(error Please select a valid configuration) endif + +# define the directories used for output products here. +BINDIR = bin/$(ARCH)/$(CONFIG) +OBJDIR = obj/$(ARCH)/$(CONFIG) diff --git a/speech2/build/rules.mk b/speech2/build/rules.mk index 38ec891..4de8247 100644 --- a/speech2/build/rules.mk +++ b/speech2/build/rules.mk @@ -1,6 +1,24 @@ + +# TODO: Handle C sources and deduplicate. +VPATH = $(dir $(CXXSRCS)) +OBJS = $(addprefix $(OBJDIR)/,$(notdir $(CXXSRCS:.cpp=.o))) + +# Build types +ifeq ($(TYPE),dll) +BUILD_PRODUCT = $(BINDIR)/$(NAME).dll + $(BINDIR)/$(NAME).dll: $(BINDIR)/ $(OBJDIR)/ $(OBJS) - echo -e "\e[92mLinking binary $@\e[0m" - $(CXX) $(OBJS) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) -o $@ + echo -e "\e[92mLinking DLL $@\e[0m" + $(CXX) $(OBJS) $(BASE_LDFLAGS_SHARED) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) -o $@ +else +ifeq ($(TYPE),exe) +BUILD_PRODUCT = $(BINDIR)/$(NAME).exe + +$(BINDIR)/$(NAME).exe: $(BINDIR)/ $(OBJDIR)/ $(OBJS) + echo -e "\e[92mLinking EXE $@\e[0m" + $(CXX) $(OBJS) $(BASE_LDFLAGS_SHARED) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) -o $@ +endif +endif $(OBJDIR)/%.o: %.c echo -e "\e[94mCompiling C source file $< ($@)\e[0m" @@ -17,3 +35,12 @@ $(OBJDIR)/%.o: %.S $(OBJDIR)/%.o: %.rc echo -e "\e[94mCompiling Windows resource script $<\e[0m" $(WINDRES) -Iinclude $< -o $@ + +# dir rules +$(BINDIR)/: + echo -e "\e[95mMKDIR $@\e[0m" + mkdir -p $(BINDIR) + +$(OBJDIR)/: + echo -e "\e[95mMKDIR $@\e[0m" + mkdir -p $(OBJDIR) diff --git a/speech2/src/bindings.cpp b/speech2/src/bindings.cpp index 5e71c1e..f492cf9 100644 --- a/speech2/src/bindings.cpp +++ b/speech2/src/bindings.cpp @@ -1,7 +1,7 @@ #include #include "speechapi.hpp" -#define SP2_EXPORT __declspec(dllexport) +#define SP2_EXPORT __declspec(dllexport) __cdecl // Engine type. Sync with C# enum class EngineType : int { ET_SAPI4, ET_SAPI5, ET_DECTALK }; @@ -10,6 +10,9 @@ extern "C" { SP2_EXPORT void* speech2_create_api(EngineType type) { ISpeechAPI* api = nullptr; + + printf("speech2_create_api(%d)\n", type); + switch(type) { case EngineType::ET_SAPI4: api = ISpeechAPI::CreateSapi4(); diff --git a/speech2/src/sapi4/api_sapi4.cpp b/speech2/src/sapi4/api_sapi4.cpp index bd70c0b..b67d7ed 100644 --- a/speech2/src/sapi4/api_sapi4.cpp +++ b/speech2/src/sapi4/api_sapi4.cpp @@ -19,7 +19,7 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI { HRESULT Initialize() override { HRESULT hRes; - printf("speech2: SpeechAPI_Sapi4::Initalize() begin\n"); + printf("speech2: SpeechAPI_Sapi4::Initalize() begin: %p\n", this); hRes = pEnum.CreateInstance(CLSID_TTSEnumerator, CLSCTX_INPROC); if(FAILED(hRes)) @@ -34,18 +34,23 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI { EnumVoices(); - printf("speech2: SpeechAPI_Sapi4::Initalize() filled out voices! Yay\n"); + printf("speech2: SpeechAPI_Sapi4::Initalize() end\n"); return S_OK; } void EnumVoices() { - static TTSMODEINFO found {}; + TTSMODEINFO found{}; + DWORD piss = 0; - while(!pEnum->Next(1, &found, nullptr)) { + + + while(!pEnum->Next(1, &found, &piss)) { //auto ptr = strdup(found.szModeName); - printf("EnumVoices() voice %p\n", &found.szModeName); + printf("EnumVoices() voice %s\n", found.szModeName); //voices.push_back(VoiceInfo { .guid = found.gModeID, .voiceName = ptr }); + + ZeroMemory(&found, sizeof(TTSMODEINFO)); } pEnum->Reset();