From 07489254a6ebe9e591d743b03ecd94b1ef937a6b Mon Sep 17 00:00:00 2001 From: Joao Henriques Date: Fri, 17 Aug 2018 18:01:40 +0100 Subject: [PATCH] added windows compilation (see issue #5, credit: mohammadkamalzare) --- .gitignore | 6 ++++++ cgco.cpp | 42 ++++++++++++++++++++++++------------------ cgco.h | 42 ++++++++++++++++++++++++------------------ cgco.py | 5 ++++- compilewindows.bat | 19 +++++++++++++++++++ pygco.py | 2 +- test.py | 13 +++++++------ 7 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 compilewindows.bat diff --git a/.gitignore b/.gitignore index daa9f06..fe53b43 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ *.o *.so test_wrapper +test_wrapper.lib +libcgco.dll +libcgco.lib +*.obj +*.exp +*.exe diff --git a/cgco.cpp b/cgco.cpp index a567584..11e27aa 100644 --- a/cgco.cpp +++ b/cgco.cpp @@ -17,6 +17,12 @@ * */ +#if defined(_MSC_VER) + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + #include #include #include @@ -49,7 +55,7 @@ void removeInstance(int handle) _gcoInstanceMap.erase(handle); } -extern "C" int gcoCreateGeneralGraph(SiteID numSites, LabelID numLabels, int *handle) +extern "C" EXPORT int gcoCreateGeneralGraph(SiteID numSites, LabelID numLabels, int *handle) { GCoptimization *gco = new GCoptimizationGeneralGraph(numSites, numLabels); _gcoInstanceMap[_gcoNextInstanceId] = gco; @@ -58,27 +64,27 @@ extern "C" int gcoCreateGeneralGraph(SiteID numSites, LabelID numLabels, int *ha return 0; } -extern "C" int gcoDestroyGraph(int handle) +extern "C" EXPORT int gcoDestroyGraph(int handle) { removeInstance(handle); return 0; } -extern "C" int gcoSetDataCost(int handle, EnergyTermType *unary) +extern "C" EXPORT int gcoSetDataCost(int handle, EnergyTermType *unary) { GCoptimization *gco = findInstance(handle); gco->setDataCost(unary); return 0; } -extern "C" int gcoSetSiteDataCost(int handle, SiteID site, LabelID label, EnergyTermType e) +extern "C" EXPORT int gcoSetSiteDataCost(int handle, SiteID site, LabelID label, EnergyTermType e) { GCoptimization *gco = findInstance(handle); gco->setDataCost(site, label, e); return 0; } -extern "C" int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermType e) +extern "C" EXPORT int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermType e) { GCoptimizationGeneralGraph *gco = (GCoptimizationGeneralGraph*)findInstance(handle); if (s1 < s2) @@ -86,7 +92,7 @@ extern "C" int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermTy return 0; } -extern "C" int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTermType *e, int nPairs) +extern "C" EXPORT int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTermType *e, int nPairs) { GCoptimizationGeneralGraph *gco = (GCoptimizationGeneralGraph*)findInstance(handle); for (int i = 0; i < nPairs; i++) @@ -95,28 +101,28 @@ extern "C" int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTerm return 0; } -extern "C" int gcoSetSmoothCost(int handle, EnergyTermType *e) +extern "C" EXPORT int gcoSetSmoothCost(int handle, EnergyTermType *e) { GCoptimization *gco = findInstance(handle); gco->setSmoothCost(e); return 0; } -extern "C" int gcoSetPairSmoothCost(int handle, LabelID l1, LabelID l2, EnergyTermType e) +extern "C" EXPORT int gcoSetPairSmoothCost(int handle, LabelID l1, LabelID l2, EnergyTermType e) { GCoptimization *gco = findInstance(handle); gco->setSmoothCost(l1, l2, e); return 0; } -extern "C" int gcoExpansion(int handle, int maxNumIters, EnergyType *e) +extern "C" EXPORT int gcoExpansion(int handle, int maxNumIters, EnergyType *e) { GCoptimization *gco = findInstance(handle); *e = gco->expansion(maxNumIters); return 0; } -extern "C" int gcoExpansionOnAlpha(int handle, LabelID label, int *success) +extern "C" EXPORT int gcoExpansionOnAlpha(int handle, LabelID label, int *success) { GCoptimization *gco = findInstance(handle); if (gco->alpha_expansion(label)) @@ -126,56 +132,56 @@ extern "C" int gcoExpansionOnAlpha(int handle, LabelID label, int *success) return 0; } -extern "C" int gcoSwap(int handle, int maxNumIters, EnergyType *e) +extern "C" EXPORT int gcoSwap(int handle, int maxNumIters, EnergyType *e) { GCoptimization *gco = findInstance(handle); *e = gco->swap(maxNumIters); return 0; } -extern "C" int gcoAlphaBetaSwap(int handle, LabelID l1, LabelID l2) +extern "C" EXPORT int gcoAlphaBetaSwap(int handle, LabelID l1, LabelID l2) { GCoptimization *gco = findInstance(handle); gco->alpha_beta_swap(l1, l2); return 0; } -extern "C" int gcoComputeEnergy(int handle, EnergyType *e) +extern "C" EXPORT int gcoComputeEnergy(int handle, EnergyType *e) { GCoptimization *gco = findInstance(handle); *e = gco->compute_energy(); return 0; } -extern "C" int gcoComputeDataEnergy(int handle, EnergyType *e) +extern "C" EXPORT int gcoComputeDataEnergy(int handle, EnergyType *e) { GCoptimization *gco = findInstance(handle); *e = gco->giveDataEnergy(); return 0; } -extern "C" int gcoComputeSmoothEnergy(int handle, EnergyType *e) +extern "C" EXPORT int gcoComputeSmoothEnergy(int handle, EnergyType *e) { GCoptimization *gco = findInstance(handle); *e = gco->giveSmoothEnergy(); return 0; } -extern "C" int gcoGetLabelAtSite(int handle, SiteID site, LabelID *label) +extern "C" EXPORT int gcoGetLabelAtSite(int handle, SiteID site, LabelID *label) { GCoptimization *gco = findInstance(handle); *label = gco->whatLabel(site); return 0; } -extern "C" int gcoGetLabels(int handle, LabelID *labels) +extern "C" EXPORT int gcoGetLabels(int handle, LabelID *labels) { GCoptimization *gco = findInstance(handle); gco->whatLabel(0, gco->numSites(), labels); return 0; } -extern "C" int gcoInitLabelAtSite(int handle, SiteID site, LabelID label) +extern "C" EXPORT int gcoInitLabelAtSite(int handle, SiteID site, LabelID label) { GCoptimization *gco = findInstance(handle); gco->setLabel(site, label); diff --git a/cgco.h b/cgco.h index a9f3558..0534ae0 100644 --- a/cgco.h +++ b/cgco.h @@ -1,6 +1,12 @@ #ifndef __CGCO_H__ #define __CGCO_H__ +#if defined(_MSC_VER) + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + #include "gco_source/GCoptimization.h" typedef GCoptimization::LabelID LabelID; @@ -12,12 +18,12 @@ typedef GCoptimization::EnergyTermType EnergyTermType; * Create a new general graph. Return an integer handle, which will be used as * the reference for the created graph instance. */ -extern "C" int gcoCreateGeneralGraph(SiteID numSites, LabelID numLabels, int *handle); +extern "C" EXPORT int gcoCreateGeneralGraph(SiteID numSites, LabelID numLabels, int *handle); /** * Destroy a graph instance referenced by given handle. */ -extern "C" int gcoDestroyGraph(int handle); +extern "C" EXPORT int gcoDestroyGraph(int handle); /** * Set data cost. @@ -25,17 +31,17 @@ extern "C" int gcoDestroyGraph(int handle); * unary should be an array of size numSites*numLabels stored in row major * order, so that dataCost(s, l) = unary[s*numLabels + l] */ -extern "C" int gcoSetDataCost(int handle, EnergyTermType *unary); +extern "C" EXPORT int gcoSetDataCost(int handle, EnergyTermType *unary); /** * Set data cost dataCost(site, label)=e. */ -extern "C" int gcoSetSiteDataCost(int handle, SiteID site, LabelID label, EnergyTermType e); +extern "C" EXPORT int gcoSetSiteDataCost(int handle, SiteID site, LabelID label, EnergyTermType e); /** * Create an edge betwen s1 and s2 with weight e. s1 should be smaller than s2. */ -extern "C" int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermType e); +extern "C" EXPORT int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermType e); /** * Setup the whole neighbor system. @@ -46,7 +52,7 @@ extern "C" int gcoSetNeighborPair(int handle, SiteID s1, SiteID s2, EnergyTermTy * Each element of s1 should be smaller than the corresponding element in s2, * otherwise the edge is ignored. */ -extern "C" int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTermType *e, int nPairs); +extern "C" EXPORT int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTermType *e, int nPairs); /** * Set the smooth cost. @@ -56,14 +62,14 @@ extern "C" int gcoSetAllNeighbors(int handle, SiteID *s1, SiteID *s2, EnergyTerm * * smoothCost(l1, l2) = e[l1*numLabels + l2] = e[l2*numLabels + l1] */ -extern "C" int gcoSetSmoothCost(int handle, EnergyTermType *e); +extern "C" EXPORT int gcoSetSmoothCost(int handle, EnergyTermType *e); /** * Set the smooth cost for a single pair of labels. * * smoothCost(l1, l2) = e */ -extern "C" int gcoSetPairSmoothCost(int handle, LabelID l1, LabelID l2, EnergyTermType e); +extern "C" EXPORT int gcoSetPairSmoothCost(int handle, LabelID l1, LabelID l2, EnergyTermType e); /** * Do alpha-expansion for a specified number of iterations. @@ -72,14 +78,14 @@ extern "C" int gcoSetPairSmoothCost(int handle, LabelID l1, LabelID l2, EnergyTe * * If maxNumIters is set to -1, it will run until convergence. */ -extern "C" int gcoExpansion(int handle, int maxNumIters, EnergyType *e); +extern "C" EXPORT int gcoExpansion(int handle, int maxNumIters, EnergyType *e); /** * Do a single alpha-expansion step on a single label. * * Return true if the energy is decreased and false otherwise. */ -extern "C" int gcoExpansionOnAlpha(int handle, LabelID label, int *success); +extern "C" EXPORT int gcoExpansionOnAlpha(int handle, LabelID label, int *success); /** * Do alpha-beta swap for a specified number of iterations. @@ -88,43 +94,43 @@ extern "C" int gcoExpansionOnAlpha(int handle, LabelID label, int *success); * * If maxNumIters is set to -1, it will run until convergence. */ -extern "C" int gcoSwap(int handle, int maxNumIters, EnergyType *e); +extern "C" EXPORT int gcoSwap(int handle, int maxNumIters, EnergyType *e); /** * Do a single alpha-beta swap for a single pair of labels. */ -extern "C" int gcoAlphaBetaSwap(int handle, LabelID l1, LabelID l2); +extern "C" EXPORT int gcoAlphaBetaSwap(int handle, LabelID l1, LabelID l2); /** * Compute the total energy for the current label assignments. */ -extern "C" int gcoComputeEnergy(int handle, EnergyType *e); +extern "C" EXPORT int gcoComputeEnergy(int handle, EnergyType *e); /** * Compute the data energy for the current label assignments. */ -extern "C" int gcoComputeDataEnergy(int handle, EnergyType *e); +extern "C" EXPORT int gcoComputeDataEnergy(int handle, EnergyType *e); /** * Compute the smooth energy for the current label assignments. */ -extern "C" int gcoComputeSmoothEnergy(int handle, EnergyType *e); +extern "C" EXPORT int gcoComputeSmoothEnergy(int handle, EnergyType *e); /** * Get the label assignment for the specified site. */ -extern "C" int gcoGetLabelAtSite(int handle, SiteID site, LabelID *label); +extern "C" EXPORT int gcoGetLabelAtSite(int handle, SiteID site, LabelID *label); /** * Get label assignments for all sites. After the call, labels[i] will be the * label assignment for site i. */ -extern "C" int gcoGetLabels(int handle, LabelID *labels); +extern "C" EXPORT int gcoGetLabels(int handle, LabelID *labels); /** * Initialize the label of a specified site to a specified label. */ -extern "C" int gcoInitLabelAtSite(int handle, SiteID site, LabelID label); +extern "C" EXPORT int gcoInitLabelAtSite(int handle, SiteID site, LabelID label); #endif // __CGCO_H__ diff --git a/cgco.py b/cgco.py index 8959ce9..7b6a6f3 100644 --- a/cgco.py +++ b/cgco.py @@ -4,7 +4,10 @@ # or change this to your own path that contains libcgco.so _CGCO_LIB_PATH = os.path.dirname(os.path.realpath(__file__)) -_CGCO_LIB_NAME = 'libcgco.so' +if os.name != 'nt': + _CGCO_LIB_NAME = 'libcgco.so' +else: + _CGCO_LIB_NAME = 'libcgco.dll' # change the type definition depending on your machine and the compiled GCO library _handle_type = ct.c_int diff --git a/compilewindows.bat b/compilewindows.bat new file mode 100644 index 0000000..1da5b4a --- /dev/null +++ b/compilewindows.bat @@ -0,0 +1,19 @@ + +@echo USAGE: +@echo ------ +@echo Open the "Developer Command Prompt for VS" +@echo For 32-bit Python, run: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat" +@echo For 64-bit Python, run: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall" amd64 +@echo Then finally run compilewindows.bat (this file) +@echo. + +@pause + +cl gco_source\LinkedBlockList.cpp /link /out:LinkedBlockList.obj +cl gco_source\graph.cpp /link /out:graph.obj +cl gco_source\maxflow.cpp /link /out:maxflow.obj +cl gco_source\GCoptimization.cpp /link /out:GCoptimization.obj +cl cgco.cpp /link /out:cgco.obj +cl LinkedBlockList.obj graph.obj maxflow.obj GCoptimization.obj cgco.obj /link /dll /out:libcgco.dll + +cl /EHsc test_wrapper.cpp libcgco.lib diff --git a/pygco.py b/pygco.py index 3505ba4..6704d15 100644 --- a/pygco.py +++ b/pygco.py @@ -11,7 +11,7 @@ _SMOOTH_COST_PRECISION = 100 _int_types = [np.int, np.intc, np.int32, np.int64, np.longlong] -_float_types = [np.float, np.float32, np.float64, np.float128] +_float_types = [np.float, np.float32, np.float64, np.longdouble] _SMALL_CONSTANT = 1e-10 diff --git a/test.py b/test.py index 9a917af..66ab69c 100644 --- a/test.py +++ b/test.py @@ -162,9 +162,10 @@ def test_binary(): fig.tight_layout(), fig.savefig('./images/binary_labels.png') -# if __name__ == "__main__": -# test_gc() -# test_integer() -# test_float() -# test_grid() -# test_binary() +if __name__ == "__main__": + test_gc() + test_integer() + test_float() + test_grid() + test_binary() + print('Passed all tests.')