Skip to content

Commit

Permalink
first steps and somewhat operational
Browse files Browse the repository at this point in the history
  • Loading branch information
ptahmose committed Oct 5, 2024
1 parent 9cdca8d commit 1a43510
Show file tree
Hide file tree
Showing 19 changed files with 590 additions and 0 deletions.
Empty file added AppModel/CMakeLists.txt
Empty file.
41 changes: 41 additions & 0 deletions AppModel/include/app_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

typedef void* Parameter;

struct IAppExtensionFunctions
{
void* (*pfn_GetData)(const Parameter* parameter);

bool (*pfn_IsNumeric)(const Parameter* parameter);

bool (*pfn_IsChar)(const Parameter* parameter);

bool (*pfn_IsSparse)(const Parameter* parameter);

bool (*pfn_IsStruct)(const Parameter* parameter);

Parameter* (*pfn_CreateString)(const char* string);

void (*pfn_ReportErrorAndRaiseSignal)(const char* identifier, const char* message);

char* (*pfn_StrDupHostAllocated)(const char* string);

Parameter* (*pfn_CreateStructArray)(size_t ndim, const size_t* dims, int nfields, const char** field_names);

void (*pfn_SetFieldByNumber)(Parameter* pa, size_t i, int fieldnum, Parameter* value);

char* (*pfn_ConvertToUTF8String)(const Parameter* parameter);

void (*pfn_Free)(void* ptr);
};

#ifdef __cplusplus
}
#endif
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ message("########################################")
]]

add_subdirectory ("MEXlibCZI")

add_subdirectory("lib")
add_subdirectory("MatlabMex")
19 changes: 19 additions & 0 deletions MatlabMex/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

set(matlabMexSourceFiles
"app_api_implementation.c"
"app_api_implementation.h"
"mex_function.cpp"
)

add_library (MatlabCZI SHARED
${matlabMexSourceFiles})
# $<TARGET_OBJECTS:lib>)

target_compile_features(MatlabCZI PRIVATE c_std_11)
target_link_libraries(MatlabCZI PRIVATE ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} lib)
target_include_directories(MatlabCZI PRIVATE ${Matlab_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../AppModel/include")
target_include_directories(MatlabCZI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../lib")

target_compile_definitions(MatlabCZI PRIVATE MW_NEEDS_VERSION_H=1)

set_target_properties(MatlabCZI PROPERTIES SUFFIX ".mexw64")
83 changes: 83 additions & 0 deletions MatlabMex/app_api_implementation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <app_api.h>
#include <mex.h>
#include <string.h>

void* matlabMexGetData(const Parameter* parameter)
{
return mxGetData((const mxArray*)parameter);
}

bool matlabMexIsNumeric(const Parameter* parameter)
{
return mxIsNumeric((const mxArray*)parameter);
}

bool matlabMexIsChar(const Parameter* parameter)
{
return mxIsChar((const mxArray*)parameter);
}

bool matlabMexIsSparse(const Parameter* parameter)
{
return mxIsSparse((const mxArray*)parameter);
}

bool matlabMexIsStruct(const Parameter* parameter)
{
return mxIsStruct((const mxArray*)parameter);
}

Parameter* matlabMexCreateString(const char* string)
{
return (Parameter*)mxCreateString(string);
}

void matlabReportErrorAndRaiseSignal(const char* identifier, const char* message)
{
mexErrMsgIdAndTxt(identifier, message);
}

char* matlabStrDupHostAllocated(const char* string)
{
size_t len = strlen(string);
char* msz = (char*)mxMalloc(len + 1);
memcpy(msz, string, len);
msz[len] = '\0';
return msz;
}

Parameter* matlabCreateStructArray(size_t ndim, const size_t* dims, int nfields, const char** field_names)
{
return (Parameter*)mxCreateStructArray(ndim, dims, nfields, field_names);
}

void matlabSetFieldByNumber(Parameter* pa, size_t i, int fieldnum, Parameter* value)
{
mxSetFieldByNumber((mxArray*)pa, i, fieldnum, (mxArray*)value);
}

char* matlabConvertToUTF8String(const Parameter* parameter)
{
return mxArrayToUTF8String((const mxArray*)parameter);
}

void matlabFree(void* ptr)
{
mxFree(ptr);
}

struct IAppExtensionFunctions g_appExtensionFunctions =
{
.pfn_GetData = matlabMexGetData,
.pfn_IsNumeric = matlabMexIsNumeric,
.pfn_IsChar = matlabMexIsChar,
.pfn_IsSparse = matlabMexIsSparse,
.pfn_IsStruct = matlabMexIsStruct,
.pfn_CreateString = matlabMexCreateString,
.pfn_ReportErrorAndRaiseSignal = matlabReportErrorAndRaiseSignal,
.pfn_StrDupHostAllocated = matlabStrDupHostAllocated,
.pfn_CreateStructArray = matlabCreateStructArray,
.pfn_SetFieldByNumber = matlabSetFieldByNumber,
.pfn_ConvertToUTF8String = matlabConvertToUTF8String,
.pfn_Free = matlabFree
};
13 changes: 13 additions & 0 deletions MatlabMex/app_api_implementation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <app_api.h>

#ifdef __cplusplus
extern "C" {
#endif

extern struct IAppExtensionFunctions g_appExtensionFunctions;

#ifdef __cplusplus
}
#endif
8 changes: 8 additions & 0 deletions MatlabMex/mex_function.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "app_api_implementation.h"
#include <mex.h>
#include <include/function.h>

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
mexlibCZI::mexFunction(nlhs, (Parameter**)plhs, nrhs, (const Parameter**)prhs, &g_appExtensionFunctions);
}
22 changes: 22 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
set (libSourceFiles
include/function.h
src/function.cpp
"src/mexFunctions.h"
"src/errorcodes.h"
"src/errorcodes.cpp"
"src/mexFunctions.cpp"
"src/functions/func_getversion.h"
"src/functions/func_getversion.cpp"
"src/implementation/inc_libczi.h"
"src/implementation/libraryinfo.h"
"src/implementation/libraryinfo.cpp"
)


add_library (lib
${libSourceFiles})

set_target_properties(lib PROPERTIES CXX_STANDARD 17)
target_include_directories(lib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../AppModel/include")
target_include_directories(lib PRIVATE ${LIBCZI_INCLUDE_DIR})
target_link_libraries(lib PRIVATE libCZIStatic JxrDecodeStatic)
9 changes: 9 additions & 0 deletions lib/include/function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <app_api.h>

namespace mexlibCZI
{
void mexFunction(int nlhs, Parameter* plhs[], int nrhs, const Parameter* prhs[], IAppExtensionFunctions* app_functions);
}

10 changes: 10 additions & 0 deletions lib/src/errorcodes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "errorcodes.h"

// cf. https://www.mathworks.com/help/matlab/apiref/mexerrmsgidandtxt.html and
// https://www.mathworks.com/help/matlab/ref/mexception.html

#define COMPONENTFIELD "MEXlibCZI"

/*static*/const char* ErrorIds::UnknownCommand = COMPONENTFIELD ":UnknownCommand";

/*static*/const char* ErrorIds::InvalidArguments = COMPONENTFIELD ":InvalidArguments";
8 changes: 8 additions & 0 deletions lib/src/errorcodes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

class ErrorIds
{
public:
static const char* UnknownCommand;
static const char* InvalidArguments;
};
81 changes: 81 additions & 0 deletions lib/src/function.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "../include/function.h"
#include <app_api.h>
#include "mexFunctions.h"
#include "errorcodes.h"
#include <exception>
#include <sstream>

using namespace mexlibCZI;
using namespace std;

void mexlibCZI::mexFunction(int nlhs, Parameter* plhs[], int nrhs, const Parameter* prhs[], IAppExtensionFunctions* app_functions)
{
if (nrhs < 1)
{
app_functions->pfn_ReportErrorAndRaiseSignal("MATLAB:MEXlibCZI:invalidNumInputs", "One input required.");
}

if (!app_functions->pfn_IsChar(prhs[0]))
{
app_functions->pfn_ReportErrorAndRaiseSignal("MATLAB:MEXlibCZI:inputNotString", "Input must be a string.");
}

bool errorOccurred = false;
char* errorText = nullptr;
const char* errorId = nullptr;

{
//auto upArgStr = mexApi.UpMxArrayToMatlabAllocatedUtf8String((const MexArray*)(prhs[0]));
char* command_name = app_functions->pfn_ConvertToUTF8String(prhs[0]);
//static_cast<const char*>(app_functions->pfn_GetData(prhs[0]));
auto func = CMexFunctions::GetInstance().FindFunc(command_name);
if (func != nullptr)
{
app_functions->pfn_Free(command_name);

MatlabArgs args = { nlhs, plhs, nrhs, prhs, app_functions };
try
{
func->pfnCheckArguments(&args);
}
catch (exception& excp)
{
errorOccurred = true;
errorText = app_functions->pfn_StrDupHostAllocated(excp.what());
errorId = ErrorIds::InvalidArguments;
}

if (!errorOccurred)
{
try
{
func->pfnExecute(&args);
}
catch (exception& excp)
{
errorOccurred = true;
errorText = app_functions->pfn_StrDupHostAllocated(excp.what());
errorId = ErrorIds::InvalidArguments;
}
}
}
else
{
errorOccurred = true;
ostringstream ss;
ss << "The string \"" << command_name << "\" is not a known command.";
app_functions->pfn_Free(command_name);
errorText = app_functions->pfn_StrDupHostAllocated(ss.str().c_str());
errorId = ErrorIds::UnknownCommand;
}
}

if (errorOccurred)
{
// Remember that we do NOT return from this call - we should make sure that no resource-cleanup is
// done beyond this point. The memory for the errorText is allocated with Matlab's malloc - therefore,
// it should be released automatically.
app_functions->pfn_ReportErrorAndRaiseSignal(errorId, errorText);
//mexApi.MexErrMsgIdAndTxt(errorId, errorText);
}
}
53 changes: 53 additions & 0 deletions lib/src/functions/func_getversion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "func_getversion.h"
//#include <stdexcept>
//#include "libraryInfo.h"
//#include <vector>
//#include "argsutils.h"
//#include "CziReaderManager.h"
//#include "utils.h"
#include "../implementation/libraryinfo.h"
#include <vector>

using namespace std;

void MexFunction_GetVersion_CheckArguments(MatlabArgs* args)
{
// nothing to check (we simply ignore all arguments which may be present)
}

void MexFunction_GetVersion_Execute(MatlabArgs* args)
{
vector<string> keys;
CLibraryInfo::EnumKeys([&](const char* keyName)->bool
{
keys.emplace_back(keyName);
return true;
});

vector<const char*> fieldNamesRawStrings;
fieldNamesRawStrings.reserve(keys.size());
for (const auto& key : keys)
{
fieldNamesRawStrings.emplace_back(key.c_str());
}

static constexpr size_t _1_by_1[2] = { 1, 1 };
auto* s = args->app_functions->pfn_CreateStructArray(
2,
_1_by_1,
static_cast<int>(keys.size()),
&fieldNamesRawStrings[0]);

for (int i = 0; i < static_cast<int>(keys.size()); ++i)
{
string value;
CLibraryInfo::GetValue(keys[i], value);
args->app_functions->pfn_SetFieldByNumber(
s,
0,
i,
args->app_functions->pfn_CreateString(value.c_str()));
}

args->plhs[0] = s;
}
6 changes: 6 additions & 0 deletions lib/src/functions/func_getversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include "../mexFunctions.h"

void MexFunction_GetVersion_CheckArguments(MatlabArgs* args);
void MexFunction_GetVersion_Execute(MatlabArgs* args);
4 changes: 4 additions & 0 deletions lib/src/implementation/inc_libczi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

#define _LIBCZISTATICLIB
#include <libCZI.h>
Loading

0 comments on commit 1a43510

Please sign in to comment.