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.
This commit is contained in:
Lily Tsuru 2024-07-19 03:59:19 -04:00
parent 126566c3cf
commit d95d305734
7 changed files with 78 additions and 36 deletions

View file

@ -1,6 +1,6 @@
build: build:
dotnet build -c Release 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 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/ cp /usr/i686-w64-mingw32/bin/libgcc_s_dw2-1.dll SAPIServer/bin/Release/net40/windows-x86/

View file

@ -36,16 +36,18 @@ namespace SAPIServer {
// Speech2 DLL API. Sync with c++ code. // Speech2 DLL API. Sync with c++ code.
internal class SpeechDLL { 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); 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); 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); 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); public static extern IntPtr speech2_api_get_voiceinfo_index(IntPtr pAPI, int index);
} }

View file

@ -2,35 +2,26 @@ include build/arch.mk
include build/configs.mk include build/configs.mk
NAME = speech2 NAME = speech2
TYPE = dll
BINDIR = bin/$(ARCH)/$(CONFIG)
OBJDIR = obj/$(ARCH)/$(CONFIG)
# Any C++ file in src/ is automatically picked up. # Any C++ file in src/ is automatically picked up.
CXXSRCS = $(wildcard src/*.cpp) $(wildcard src/*/*.cpp) CXXSRCS = $(wildcard src/*.cpp) $(wildcard src/*/*.cpp)
VPATH = $(dir $(CXXSRCS))
OBJS = $(addprefix $(OBJDIR)/,$(notdir $(CXXSRCS:.cpp=.o)))
.PHONY: all dumpinfo clean matrix .PHONY: all 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)
include build/rules.mk include build/rules.mk
all: $(BUILD_PRODUCT)
clean: clean:
echo -e "\e[91mCleaning... \e[0m" echo -e "\e[91mCleaning... \e[0m"
rm -rf $(BINDIR)/ $(OBJS) 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: $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) -include $(OBJS:.o=.d)

View file

@ -1,11 +1,21 @@
# Base compiler flags. Only change if you *explicitly* know what you're doing. # 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 #ifeq ($(VCDIR),)
BASE_LDFLAGS = -Wl,--subsystem=windows -fvisibility=hidden -shared -lkernel32 -lshell32 -luser32 -luuid -lole32 #$(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_Valid = yes
Release_CCFLAGS = -O3 -ffast-math -fomit-frame-pointer -DNDEBUG Release_CCFLAGS = -O3 -DNDEBUG
Release_CXXFLAGS = -O3 -ffast-math -fomit-frame-pointer -DNDEBUG Release_CXXFLAGS = -O3 -DNDEBUG
Release_LDFLAGS = -s Release_LDFLAGS = -s
Debug_Valid = yes Debug_Valid = yes
@ -21,3 +31,7 @@ endif
ifneq ($($(CONFIG)_Valid),yes) ifneq ($($(CONFIG)_Valid),yes)
$(error Please select a valid configuration) $(error Please select a valid configuration)
endif endif
# define the directories used for output products here.
BINDIR = bin/$(ARCH)/$(CONFIG)
OBJDIR = obj/$(ARCH)/$(CONFIG)

View file

@ -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) $(BINDIR)/$(NAME).dll: $(BINDIR)/ $(OBJDIR)/ $(OBJS)
echo -e "\e[92mLinking binary $@\e[0m" echo -e "\e[92mLinking DLL $@\e[0m"
$(CXX) $(OBJS) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) -o $@ $(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 $(OBJDIR)/%.o: %.c
echo -e "\e[94mCompiling C source file $< ($@)\e[0m" echo -e "\e[94mCompiling C source file $< ($@)\e[0m"
@ -17,3 +35,12 @@ $(OBJDIR)/%.o: %.S
$(OBJDIR)/%.o: %.rc $(OBJDIR)/%.o: %.rc
echo -e "\e[94mCompiling Windows resource script $<\e[0m" echo -e "\e[94mCompiling Windows resource script $<\e[0m"
$(WINDRES) -Iinclude $< -o $@ $(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)

View file

@ -1,7 +1,7 @@
#include <windows.h> #include <windows.h>
#include "speechapi.hpp" #include "speechapi.hpp"
#define SP2_EXPORT __declspec(dllexport) #define SP2_EXPORT __declspec(dllexport) __cdecl
// Engine type. Sync with C# // Engine type. Sync with C#
enum class EngineType : int { ET_SAPI4, ET_SAPI5, ET_DECTALK }; enum class EngineType : int { ET_SAPI4, ET_SAPI5, ET_DECTALK };
@ -10,6 +10,9 @@ extern "C" {
SP2_EXPORT void* speech2_create_api(EngineType type) { SP2_EXPORT void* speech2_create_api(EngineType type) {
ISpeechAPI* api = nullptr; ISpeechAPI* api = nullptr;
printf("speech2_create_api(%d)\n", type);
switch(type) { switch(type) {
case EngineType::ET_SAPI4: case EngineType::ET_SAPI4:
api = ISpeechAPI::CreateSapi4(); api = ISpeechAPI::CreateSapi4();

View file

@ -19,7 +19,7 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI {
HRESULT Initialize() override { HRESULT Initialize() override {
HRESULT hRes; 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); hRes = pEnum.CreateInstance(CLSID_TTSEnumerator, CLSCTX_INPROC);
if(FAILED(hRes)) if(FAILED(hRes))
@ -34,18 +34,23 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI {
EnumVoices(); EnumVoices();
printf("speech2: SpeechAPI_Sapi4::Initalize() filled out voices! Yay\n"); printf("speech2: SpeechAPI_Sapi4::Initalize() end\n");
return S_OK; return S_OK;
} }
void EnumVoices() { 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); //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 }); //voices.push_back(VoiceInfo { .guid = found.gModeID, .voiceName = ptr });
ZeroMemory(&found, sizeof(TTSMODEINFO));
} }
pEnum->Reset(); pEnum->Reset();