Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# Opening Tables
*.book

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Compiled Dynamic libraries
*.so
*.dll
*.def

# Precompiled Headers
*.gch
*.pch
Expand All @@ -29,3 +37,9 @@

# vim swap file
*.swp

# Make artifacts
.depend

# Visual Studio
.vs
34 changes: 26 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
CXX=g++
CXXFLAGS=--std=c++11 -W -Wall -O3 -DNDEBUG
CXXFLAGS=--std=c++11 -W -Wall -O3 -DNDEBUG -fPIC
LDLIBS=

SRCS=Solver.cpp
OBJS=$(subst .cpp,.o,$(SRCS))

c4solver:$(OBJS) main.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o c4solver main.o $(OBJS) $(LDLIBS)
ifeq ($(OS),Windows_NT) # Windows
SHARED_LIB_EXT=dll
LDFLAGS=-Wl,--output-def,solver_c_interface.def -Wl,--export-all-symbols -Wl,--out-implib,solver_c_interface.lib
else # Linux/macOS
SHARED_LIB_EXT=so
LDFLAGS=
endif

all: c4solver generator c4solver_c_interface

c4solver: $(OBJS) main.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o c4solver main.o $(OBJS) $(LDLIBS)

generator: generator.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o generator generator.o $(LDLIBS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o generator generator.o $(LDLIBS)

c4solver_c_interface: $(OBJS) solver_c_interface.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o c4solver_c_interface.$(SHARED_LIB_EXT) solver_c_interface.o $(OBJS) $(LDLIBS)

.depend: $(SRCS)
$(CXX) $(CXXFLAGS) -MM $^ > ./.depend
$(CXX) $(CXXFLAGS) -MM $^ > ./.depend

-include .depend

clean:
rm -f *.o .depend c4solver generator

ifeq ($(OS),Windows_NT)
del *.o .depend c4solver.exe generator.exe c4solver_c_interface.dll c4solver_c_interface.def c4solver_c_interface.lib
else
rm -f *.o .depend c4solver generator c4solver_c_interface.so
endif

PHONY: clean all
25 changes: 25 additions & 0 deletions c_interface_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import ctypes

# Load the shared library
solver_lib = ctypes.CDLL(r"./c4solver_c_interface.dll")

# Define argument and return types
solver_lib.solver_init.argtypes = [ctypes.c_char_p]
solver_lib.solver_init.restype = ctypes.POINTER(ctypes.c_void_p)

solver_lib.solver_delete.argtypes = [ctypes.POINTER(ctypes.c_void_p)]
solver_lib.solver_delete.restype = None

solver_lib.solver_solve.argtypes = [ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.c_bool, ctypes.c_bool, ctypes.c_char_p, ctypes.c_size_t]
solver_lib.solver_solve.restype = ctypes.c_char_p

# Example usage
handle = solver_lib.solver_init(None) #or None for default
result_buffer = ctypes.create_string_buffer(256)
result = solver_lib.solver_solve(handle, b"123", True, False, result_buffer, 256)
print(result.decode())

result = solver_lib.solver_solve(handle, b"123445622", False, True, result_buffer, 256)
print(result.decode())

solver_lib.solver_delete(handle)
4 changes: 3 additions & 1 deletion generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <sstream>
#include <string>
#include <unordered_set>
#include <vector>

using namespace GameSolver::Connect4;

Expand Down Expand Up @@ -81,7 +82,8 @@ void generate_opening_book() {
int main(int argc, char** argv) {
if(argc > 1) {
int depth = atoi(argv[1]);
char pos_str[depth + 1] = {0};
std::vector<char> pos_vec(depth + 1, 0);
char* pos_str = pos_vec.data();
explore(Position(), pos_str, depth);
} else generate_opening_book();
}
66 changes: 66 additions & 0 deletions solver_c_interface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include "Solver.hpp"

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

using namespace GameSolver::Connect4;

extern "C" {

struct SolverHandle {
Solver solver;
};

DLLEXPORT SolverHandle* solver_init(const char* opening_book) {
SolverHandle* handle = new SolverHandle;
handle->solver.loadBook(opening_book ? opening_book : "7x6.book");
return handle;
}

DLLEXPORT void solver_delete(SolverHandle* handle) {
delete handle;
}

DLLEXPORT const char* solver_solve(SolverHandle* handle, const char* past_moves, bool weak, bool analyze, char* result_buffer, size_t buffer_size) {
if (!handle || !past_moves || !result_buffer || buffer_size == 0) {
return nullptr;
}

Position P;
std::string moves_str(past_moves);
if (P.play(moves_str) != moves_str.size()) {
snprintf(result_buffer, buffer_size, "Invalid move");
return result_buffer;
}

std::stringstream ss;
ss << moves_str;

if (analyze) {
std::vector<int> scores = handle->solver.analyze(P, weak);
for (int score : scores) {
ss << " " << score;
}
}
else {
int score = handle->solver.solve(P, weak);
ss << " " << score;
}

std::string result = ss.str();
if (result.size() >= buffer_size) {
snprintf(result_buffer, buffer_size, "Result too long");
return result_buffer;
}

strcpy(result_buffer, result.c_str());
return result_buffer;
}
}