summaryrefslogtreecommitdiff
path: root/src/DB_interfaces/api_db/DLL_interface.cpp
blob: 9e173f2821d403abd86d3de51d9429feafc87b4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
 *  File:    DLL_interface.cpp
 *
 *  Author:  Beat Forster (bfo@synthesis.ch)
 *
 *
 *  General interface to access the routines
 *  of a DLL.
 *
 *  Copyright (c) 2004-2011 by Synthesis AG + plan44.ch
 *
 *
 */


#include "sync_include.h"
#include "sync_dbapidef.h"
#include "sync_dbapiconnect.h"
#include "SDK_util.h"
#include "SDK_support.h"
#include "DLL_interface.h"

#ifdef ANDROID
  #include "android/log.h"
#endif

#ifdef SYSYNC_ENGINE
  #include "syncappbase.h"
#endif

#ifdef JNI_SUPPORT
  #include "JNI_interface.h"
#endif

#ifdef __cplusplus
  namespace sysync {
#endif


// ------------------------------------------------------------------
#ifdef PLUGIN_DLL
//! derived class for DLL access
bool TDLL::Connect( cAppCharP aModName, ErrReport aReport, void* /* ref */ )
{
                           fModName= Plugin_MainName( aModName );
  return ConnectDLL( fMod, fModName.c_str(), aReport );
} // TDLL::Connect


bool TDLL::GetFunction( cAppCharP aFuncName, cAppCharP /* aParams */,
                       appPointer    &aFunc, ErrMReport aReport, void* ref )
{
  appPointer m; /* don't overwrite <aFunc> if "" or in case of error */
  if                     (*aFuncName=='\0')              return true;
  if (!DLL_Function( fMod, aFuncName, m  )) {
             aReport( ref, aFuncName,fModName.c_str() ); return false; }

  aFunc= m; return true;
} // TDLL::GetFunction


bool TDLL::Disconnect() {
  return DisconnectDLL( fMod );
} // TDLL::Disconnect
#endif // PLUGIN_DLL


// ---- Handler for DLL connection reporting ------------------------
static void ReportPuts( cAppCharP aText )
{
  #ifdef ANDROiD
    __android_log_write( ANDROID_LOG_DEBUG, "ReportError", aText );
  #else
    ConsolePrintf( aText );
  #endif
} // ReportPuts


void Report_Error( cAppCharP aText, ... )
{
  const sInt16 maxmsglen=1024;
  char msg[maxmsglen];
  va_list args;

  msg[0]='\0';
  va_start(args, aText);
  // assemble the message string
  vsnprintf(msg, maxmsglen, aText, args);
  va_end(args);

  // write the string
  ReportPuts( msg );
}


void ModuleConnectionError( void* /* ref */, cAppCharP aModName )
{
  string               s= "Can't connect to library "  + Apo(  aModName ) + ".";
  Report_Error       ( s.c_str() );
} // ModuleConnectionError


void FuncConnectionError( void* /* ref */, cAppCharP aFuncName, cAppCharP aModName )
{
  string               s= "Can't connect to function " + Apo( aFuncName );
  if (*aModName!='\0') s+= " of module "               + Apo(  aModName );
                       s+= ".";
  Report_Error       ( s.c_str() );
} // FuncConnectionError



// ------------------------------------------------------------------
static TAccess* AssignedObject( cAppCharP name, bool is_jni )
// Create object for LIB or DLL or JNI
{
  TAccess* d     = NULL;
  bool     is_lib= false;

  do {
    #ifdef JNI_SUPPORT
      if (is_jni) { d= static_cast<TAccess*>( new TJNI_Methods ); break; } // JNI (Java)
    #endif

          is_lib= IsLib( name );
    if   (is_lib) { d=                        new TAccess;        break; } // LIB direct

    #ifdef PLUGIN_DLL
                    d= static_cast<TAccess*>( new TDLL );         break;   // DLL (C/C++)
    #endif
  } while (false);

  if (d==NULL) return NULL;

  d->fJNI= is_jni;
  d->fLIB= is_lib;

  return d;
} // AssignedObject

static void FreeAssignedObject( TAccess* d )
{
  do {
    #ifdef JNI_SUPPORT
      if (d->fJNI) { TJNI_Methods* dj= static_cast<TJNI_Methods*>( d );
                     delete        dj; break; } // JNI (Java)
    #endif

    if   (d->fLIB) { delete        d;  break; } // LIB direct

    #ifdef PLUGIN_DLL
                   { TDLL*         dd= static_cast<TDLL*>( d );
                     delete        dd; break; } // DLL (C/C++)
    #endif
  } while (false);
}


// ------------------------------------------------------------------
TSyError ConnectModule( appPointer &aMod, cAppCharP aModName, bool is_jni )
{
  TAccess* d= AssignedObject( aModName, is_jni );
  if     (!d)        return DB_Forbidden;
  if      (d->Connect       ( aModName,ModuleConnectionError ))
       { aMod=    d; return LOCERR_OK;   }
  else { aMod= NULL; FreeAssignedObject(d); return DB_NotFound; }
} // ConnectModule



TSyError ConnectFunctions( appPointer aMod, appPointer aField, memSize aFieldSize,
                           bool aParamInfo, ... )
/* Connect to DLL <aDLLname> (or LIB if <aDLLname> = "") */
{
  TSyError    err      = LOCERR_OK;
  TAccess*    d        = (TAccess*)aMod;
  char*       p        = NULL;
  char*       q;
  appPointer* m        = (appPointer*)aField;
  bool        notEnough= false;
  bool        tooMany  = false;

  if (aParamInfo) aFieldSize= 2*aFieldSize;

  // do vararg handling
  va_list   args;
  va_start( args, aParamInfo ); // the element before the open param list

  // now go thru the list of all functions and put them into the list
  uInt32 ii= 0;
  while (ii*sizeof(p)<=aFieldSize) {
      p= va_arg( args, char* ); if (p==NULL) break;
      if (p==(char*)XX)
          p= NULL; // XX is equivalent to NULL, but not termination of the list
      q= NULL;

    // if aParamInfo, treat them as a pair <p>,<q>
    if (aParamInfo) {
      q= va_arg( args, char* ); if (q==NULL) break;
      ii++;
    } // if
    ii++;

  if (!err) {
      bool ok= d->GetFunction( p,q, *m, FuncConnectionError );
      if (!ok) err= DB_NotFound;
  } // if

    m++;
  } // while
  if (err) goto done;

  // check if table is too small or too long
  while (ii*sizeof(p)<aFieldSize) {
    notEnough= true;
    *m= NULL; // initialize the rest to zero
    m++;
                    ii++;
    if (aParamInfo) ii++;
  } // while
  tooMany= (p!=NULL);


  if (notEnough || tooMany) err = LOCERR_WRONGUSAGE;
 done:
  va_end( args );
  return err;
} // ConnectFunctions



TSyError DisconnectModule( appPointer &aMod )
{
  TAccess* d  = (TAccess*)aMod;
  TSyError err= LOCERR_OK;

  if  (d==NULL)  return err;
  if (!d->Disconnect()) err= DB_NotFound;
  FreeAssignedObject(d);

  aMod= NULL; // no longer access
  return err;
} // DisconnectModule


#ifdef __cplusplus
  } // namespace
#endif

/* eof */