Skip to content

Commit

Permalink
Make extern "C" stuff in SML clearer
Browse files Browse the repository at this point in the history
Move the `extern "C"` into the files where possible; that way we don't have an
extra `}` in the middle of the file that's disconnected syntactically from its
matching brace. I could not find the declaration for Tcl or Python, though
(and these use std::string directly still, so apparently no one ever cared about
making sure these had a C ABI in the DLL). We'll cross that bridge when we get
to it.

Add explanatory comments to the prevResult cacheing needed by
`RhsEventHandler`s and `ClientEventHandler`s.
  • Loading branch information
garfieldnate committed Aug 17, 2023
1 parent 5dbbe9c commit adec436
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 44 deletions.
19 changes: 17 additions & 2 deletions Core/ClientSMLSWIG/CSharp/CSharpCallbackByHand.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
// that SWIG can't auto generate.
//

#ifdef __cplusplus
// We expose the public methods in a DLL with C naming (not C++ mangled names)
extern "C" {
#endif

// __stcall calling convention only applicable to 32-bit Windows
#if defined(_WIN32) && !defined(_WIN64)
#define STDCALL __stdcall
Expand Down Expand Up @@ -813,8 +818,9 @@ typedef char const* (STDCALL* ClientMessageCallback)(int eventID, CallbackDataPt
// Then from here we need to call back to C# to pass back the message.
static const char *RhsEventHandler(sml::smlRhsEventId /*id*/, void* pUserData, sml::Agent* pAgent, char const* pFunctionName, char const* pArgument, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand All @@ -837,6 +843,8 @@ static const char *RhsEventHandler(sml::smlRhsEventId /*id*/, void* pUserData, s
// Now try to call back to CSharp
std::string res = callback(pData->m_EventID, pData->m_CallbackData, pData->m_Kernel, csharpAgentName, csharpFunctionName, csharpArgument) ;

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( res.length() + 1 > *bufSize )
{
*bufSize = res.length() + 1;
Expand All @@ -852,8 +860,10 @@ static const char *RhsEventHandler(sml::smlRhsEventId /*id*/, void* pUserData, s
// Then from here we need to call back to C# to pass back the message.
static const char *ClientEventHandler(sml::smlRhsEventId /*id*/, void* pUserData, sml::Agent* pAgent, char const* pClientName, char const* pMessage, int *bufSize, char *buf )
{
static std::string prevResult;

// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;
if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand All @@ -876,6 +886,8 @@ static const char *ClientEventHandler(sml::smlRhsEventId /*id*/, void* pUserData
// Now try to call back to CSharp
std::string res = callback(pData->m_EventID, pData->m_CallbackData, pData->m_Kernel, csharpAgentName, csharpClientName, csharpMessage) ;

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( res.length() + 1 > *bufSize )
{
*bufSize = res.length() + 1;
Expand Down Expand Up @@ -1045,3 +1057,6 @@ SWIGEXPORT bool SWIGSTDCALL CSharp_Kernel_UnregisterForAgentEvent(void* jarg1, i
return result ;
}

#ifdef __cplusplus
} // extern "C"
#endif
8 changes: 1 addition & 7 deletions Core/ClientSMLSWIG/CSharp/CSharp_sml_ClientInterface.i
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,6 @@
//%newobject sml::Kernel::CreateRemoteConnection;

%{
#ifdef __cplusplus
extern "C" {
#endif
#include "CSharpCallbackByHand.h"
#ifdef __cplusplus
}
#endif
%}
%}

19 changes: 17 additions & 2 deletions Core/ClientSMLSWIG/Java/JavaCallbackByHand.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ int jUpdateCallback = pKernel.RegisterForSystemEvent(pKernel, smlEventId.smlEVEN
// A native thread cannot be attached simultaneously to two Java VMs.
// When a thread is attached to the VM, the context class loader is the bootstrap loader.

#ifdef __cplusplus
// We expose the public methods in a DLL with C naming (not C++ mangled names)
extern "C" {
#endif

#include <string>
#include <list>

Expand Down Expand Up @@ -1103,8 +1108,9 @@ JNIEXPORT bool JNICALL Java_sml_smlJNI_Kernel_1UnregisterForStringEvent(JNIEnv *
static const char *RhsEventHandler(sml::smlRhsEventId id, void* pUserData, sml::Agent* pAgent,
char const* pFunctionName, char const* pArgument, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -1173,6 +1179,8 @@ static const char *RhsEventHandler(sml::smlRhsEventId id, void* pUserData, sml::
jenv->ReleaseStringUTFChars(result, pResult);
}

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( resultStr.length() + 1 > *bufSize )
{
*bufSize = resultStr.length() + 1;
Expand All @@ -1189,8 +1197,9 @@ static const char *RhsEventHandler(sml::smlRhsEventId id, void* pUserData, sml::
static const char *ClientMessageHandler(sml::smlRhsEventId id, void* pUserData, sml::Agent* pAgent,
char const* pFunctionName, char const* pArgument, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -1259,6 +1268,8 @@ static const char *ClientMessageHandler(sml::smlRhsEventId id, void* pUserData,
jenv->ReleaseStringUTFChars(result, pResult);
}

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( resultStr.length() + 1 > *bufSize )
{
*bufSize = resultStr.length() + 1;
Expand Down Expand Up @@ -1441,3 +1452,7 @@ JNIEXPORT bool JNICALL Java_sml_smlJNI_Kernel_1UnregisterForAgentEvent(JNIEnv *j

return result ;
}

#ifdef __cplusplus
} // extern "C"
#endif
52 changes: 23 additions & 29 deletions Core/ClientSMLSWIG/Java/Java_sml_ClientInterface.i
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
throw e ;
}
}

public final static native long Agent_RegisterForRunEvent(long jarg1, int jarg2, Object jarg3, Object jarg4, Object jarg6);
public final static native long Agent_RegisterForProductionEvent(long jarg1, int jarg2, Object jarg3, Object jarg4, Object jarg6);
public final static native long Agent_RegisterForPrintEvent(long jarg1, int jarg2, Object jarg3, Object jarg4, Object jarg6, boolean jarg7);
Expand Down Expand Up @@ -87,26 +87,26 @@
public interface ProductionEventInterface {
public void productionEventHandler(int eventID, Object data, Agent agent, String prodName, String instantiation) ;
}
public interface PrintEventInterface {

public interface PrintEventInterface {
public void printEventHandler(int eventID, Object data, Agent agent, String message) ;
}

public interface xmlEventInterface {
public void xmlEventHandler(int eventID, Object data, Agent agent, ClientXML xml) ;
}

public interface OutputEventInterface {
public interface OutputEventInterface {
public void outputEventHandler(Object data, String agentName, String attributeName, WMElement pWmeAdded) ;
}

public interface OutputNotificationInterface {
public void outputNotificationHandler(Object data, Agent agent) ;
}

public long RegisterForRunEvent(smlRunEventId id, RunEventInterface handlerObject, Object callbackData)
{ return smlJNI.Agent_RegisterForRunEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ;}

public long RegisterForProductionEvent(smlProductionEventId id, ProductionEventInterface handlerObject, Object callbackData)
{ return smlJNI.Agent_RegisterForProductionEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ; }

Expand All @@ -118,7 +118,7 @@

public long RegisterForXMLEvent(smlXMLEventId id, xmlEventInterface handlerObject, Object callbackData)
{ return smlJNI.Agent_RegisterForXMLEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ; }

public long RegisterForOutputNotification(OutputNotificationInterface handlerObject, Object callbackData)
{ return smlJNI.Agent_RegisterForOutputNotification(swigCPtr, this, handlerObject, callbackData) ;}

Expand Down Expand Up @@ -149,29 +149,29 @@
public void systemEventHandler(int eventID, Object data, Kernel kernel) ;
}

public interface UpdateEventInterface {
public interface UpdateEventInterface {
public void updateEventHandler(int eventID, Object data, Kernel kernel, int runFlags) ;
}

public interface StringEventInterface {
public interface StringEventInterface {
public String stringEventHandler(int eventID, Object userData, Kernel kernel, String callbackData) ;
}

public interface AgentEventInterface {
public interface AgentEventInterface {
public void agentEventHandler(int eventID, Object data, String agentName) ;
}

public interface RhsFunctionInterface {
public interface RhsFunctionInterface {
public String rhsFunctionHandler(int eventID, Object data, String agentName, String functionName, String argument) ;
}

public interface ClientMessageInterface {
public interface ClientMessageInterface {
public String clientMessageHandler(int eventID, Object data, String agentName, String functionName, String argument) ;
}

public long RegisterForSystemEvent(smlSystemEventId id, SystemEventInterface handlerObject, Object callbackData)
{ return smlJNI.Kernel_RegisterForSystemEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ;}

public boolean UnregisterForSystemEvent(long callbackReturnValue)
{ return smlJNI.Kernel_UnregisterForSystemEvent(swigCPtr, callbackReturnValue) ;}

Expand All @@ -183,10 +183,10 @@

public long RegisterForStringEvent(smlStringEventId id, StringEventInterface handlerObject, Object callbackData)
{ return smlJNI.Kernel_RegisterForStringEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ;}

public boolean UnregisterForStringEvent(long callbackReturnValue)
{ return smlJNI.Kernel_UnregisterForStringEvent(swigCPtr, callbackReturnValue) ;}

public long RegisterForAgentEvent(smlAgentEventId id, AgentEventInterface handlerObject, Object callbackData)
{ return smlJNI.Kernel_RegisterForAgentEvent(swigCPtr, id.swigValue(), this, handlerObject, callbackData) ; }

Expand All @@ -212,7 +212,7 @@
smlJNI.Kernel_ShutdownInternal(swigCPtr, this);
delete() ;
}

// Allow a user to avoid deleting the kernel object immediately, if they have some special reason.
public void ShutdownNoDelete()
{
Expand All @@ -230,20 +230,20 @@
public void addAttribute(String attributeName, String valueName) {
AddAttribute(attributeName, valueName) ;
}

public String getAttributeThrows(String name) throws Exception {
String value = GetAttribute(name) ;
if (value == null)
throw new Exception("Could not find attribute " + name + " while parsing XML document") ;
throw new Exception("Could not find attribute " + name + " while parsing XML document") ;
return value ;
}
}

public int getAttributeIntThrows(String name) throws Exception {
String val = getAttributeThrows(name) ;
int intVal = Integer.parseInt(val) ;
return intVal ;
}

private long GetCPtrAndDisown(ElementXML pChild) {
pChild.swigCMemOwn = false;
return ElementXML.getCPtr(pChild);
Expand Down Expand Up @@ -275,11 +275,5 @@


%{
#ifdef __cplusplus
extern "C" {
#endif
#include "JavaCallbackByHand.h"
#ifdef __cplusplus
}
#endif
%}
%}
10 changes: 8 additions & 2 deletions Core/ClientSMLSWIG/Python/Python_sml_ClientInterface.i
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,9 @@

const char *PythonRhsEventCallback(sml::smlRhsEventId id, void* pUserData, sml::Agent* pAgent, char const* pFunctionName, char const* pArgument, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -318,6 +319,8 @@

PyGILState_Release(gstate); /* Release the thread. No Python API allowed beyond this point. */

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( res.length() + 1 > *bufSize )
{
*bufSize = res.length() + 1;
Expand All @@ -331,8 +334,9 @@

const char *PythonClientMessageEventCallback(sml::smlRhsEventId id, void* pUserData, sml::Agent* pAgent, char const* pClientName, char const* pMessage, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -364,6 +368,8 @@

PyGILState_Release(gstate); /* Release the thread. No Python API allowed beyond this point. */

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( res.length() + 1 > *bufSize )
{
*bufSize = res.length() + 1;
Expand Down
10 changes: 8 additions & 2 deletions Core/ClientSMLSWIG/Tcl/Tcl_sml_ClientInterface.i
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@
const char *TclRhsEventCallback(sml::smlRhsEventId, void* pUserData, sml::Agent* pAgent, char const* pFunctionName,
char const* pArgument, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -197,6 +198,8 @@

std::string sres = Tcl_GetString(res);

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( sres.length() + 1 > *bufSize )
{
*bufSize = sres.length() + 1;
Expand All @@ -211,8 +214,9 @@
const char *TclClientMessageEventCallback(sml::smlRhsEventId, void* pUserData, sml::Agent* pAgent, char const* pClientName,
char const* pMessage, int *bufSize, char *buf)
{
// Previous result was cached, meaning client should be calling again to get it
// return that result and clear the cache
static std::string prevResult;

if ( !prevResult.empty() )
{
strncpy( buf, prevResult.c_str(), *bufSize );
Expand Down Expand Up @@ -244,6 +248,8 @@

std::string sres = Tcl_GetString(res);

// Too long to fit in the buffer; cache result and signal client with
// NULL return value to call again with a larger buffer
if ( sres.length() + 1 > *bufSize )
{
*bufSize = sres.length() + 1;
Expand Down

0 comments on commit adec436

Please sign in to comment.