Changeset 4557


Ignore:
Timestamp:
Jul 11, 2013 5:35:05 AM (8 years ago)
Author:
nanang
Message:

JNI project:

  • mapped pj_str_t and java String
  • cosmetics: tabs consistency
Location:
pjproject/branches/projects/jni
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile

    r4549 r4557  
    2121MY_OUT_DIR       = output 
    2222MY_SWIG_IF       = $(MY_OUT_DIR)/pjsua.i 
    23 MY_SWIG_FLAG     = -c++ -I$(MY_OUT_DIR) # -Wall 
     23MY_SWIG_FLAG     = -c++ -I$(MY_OUT_DIR) # -debug-tmsearch -debug-tmused # -Wall 
    2424MY_SWIG_WRAPPER  = $(MY_OUT_DIR)/pjsua_wrap 
    2525MY_PACKAGE_SRC   = $(MY_OUT_DIR)/src/$(subst .,/,$(MY_PACKAGE)) 
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i

    r4549 r4557  
    66 
    77%feature("director") PjsuaCallback; 
     8%ignore pjsua_callback; 
    89%ignore pjsua_config::cb; 
    910%extend pjsua_config { 
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i

    r4549 r4557  
    1616 
    1717/* Map 'void *' simply as long, app can use this "long" as index of its real user data */ 
    18 %apply long { void * }; 
     18%apply long long { void * }; 
    1919 
    2020/* Handle void *[ANY], e.g: pjsip_tx_data::mod_data, pjsip_transaction::mod_data */ 
    2121//%ignore pjsip_tx_data::mod_data; 
    2222//%ignore pjsip_transaction::mod_data; 
    23 %apply long[ANY] { void *[ANY] }; 
     23%apply long long[ANY]  { void *[ANY] }; 
    2424 
    2525/* Map "int*" & "unsigned*" as input & output */ 
    2626%apply unsigned *INOUT  { unsigned * }; 
    27 %apply int      *INOUT  { int * }; 
     27%apply int      *INOUT  { int * }; 
    2828 
    2929/* Map the following args as input & output */ 
    30 %apply int      *INOUT  { pj_stun_nat_type * }; 
    31 %apply int      *INOUT  { pjsip_status_code * }; 
    32 %apply int[ANY]         { pjmedia_format_id dec_fmt_id[ANY] }; 
     30%apply int      *INOUT  { pj_stun_nat_type * }; 
     31%apply int      *INOUT  { pjsip_status_code * }; 
     32%apply int[ANY]         { pjmedia_format_id dec_fmt_id[ANY] }; 
     33%apply pj_str_t *INOUT  { pj_str_t *p_contact }; 
    3334 
    34 /* Handle array of pj_str_t */ 
    35 JAVA_ARRAYSOFCLASSES(pj_str_t) 
     35/* Handle members typed array of pj_str_t */ 
     36MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, nameserver, nameserver_count) 
     37MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, outbound_proxy, outbound_proxy_cnt) 
     38MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt) 
     39MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_acc_config, proxy, proxy_cnt) 
     40MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt) 
     41MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt) 
     42MY_JAVA_MEMBER_ARRAY_OF_STR(pjsip_generic_array_hdr, values, count) 
    3643 
    3744/* Handle pointer-to-pointer-to-object as input & output */ 
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java

    r4549 r4557  
    44import java.io.InputStreamReader; 
    55import java.io.IOException; 
     6 
     7import org.pjsip.pjsua.pj_pool_t; 
     8import org.pjsip.pjsua.pjsip_rx_data; 
     9import org.pjsip.pjsua.pjsip_transport_type_e; 
     10 
    611import org.pjsip.pjsua.pjsua; 
    712import org.pjsip.pjsua.pjsua_acc_config; 
     
    1116import org.pjsip.pjsua.pjsua_logging_config; 
    1217import org.pjsip.pjsua.pjsua_transport_config; 
    13 import org.pjsip.pjsua.pjsip_transport_type_e; 
    14 import org.pjsip.pjsua.pj_str_t; 
    1518import org.pjsip.pjsua.PjsuaCallback; 
    1619 
     
    1922        public void on_call_media_state(int call_id) 
    2023        { 
    21             System.out.println("======== Call media started (call id: " + call_id + ")"); 
    22             pjsua_call_info info = new pjsua_call_info(); 
    23             pjsua.call_get_info(call_id, info); 
    24             if (info.getMedia_status() == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) { 
    25                 pjsua.conf_connect(info.getConf_slot(), 0); 
    26                 pjsua.conf_connect(0, info.getConf_slot()); 
    27             } 
     24                System.out.println("======== Call media started (call id: " + call_id + ")"); 
     25                pjsua_call_info info = new pjsua_call_info(); 
     26                pjsua.call_get_info(call_id, info); 
     27                if (info.getMedia_status() == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) { 
     28                        pjsua.conf_connect(info.getConf_slot(), 0); 
     29                        pjsua.conf_connect(0, info.getConf_slot()); 
     30                } 
     31        } 
     32        @Override 
     33        public void on_pager(int call_id, String from, String to, String contact, String mime_type, String body) 
     34        { 
     35                System.out.println("======== Incoming pager (call id: " + call_id + ")"); 
     36                System.out.println("From     : " + from); 
     37                System.out.println("To       : " + to); 
     38                System.out.println("Contact  : " + contact); 
     39                System.out.println("Mimetype : " + mime_type); 
     40                System.out.println("Body     : " + body); 
     41        } 
     42        @Override 
     43        public void on_incoming_call(int acc_id, int call_id, pjsip_rx_data rdata) { 
     44                /* Auto answer */ 
     45                pjsua.call_answer(call_id, 200, null, null); 
    2846        } 
    2947} 
     
    4058        } 
    4159 
    42         protected static pj_str_t pj_str(String st) { 
    43                 pj_str_t st_ = new pj_str_t(); 
    44                 st_.setPtr(st); 
    45                 st_.setSlen(st.length()); 
    46                 return st_; 
    47         } 
    48          
    4960        public static void main(String[] args) { 
    5061                int[] tp_id = new int[1]; 
     
    105116                 
    106117                /* Make call to the URL. */ 
    107                 { 
    108                         pj_str_t call_target = pj_str("sip:localhost"); 
    109                         status = pjsua.call_make_call(acc_id[0], call_target, null, 0, null, call_id); 
     118                if (false) { 
     119                        status = pjsua.call_make_call(acc_id[0], "sip:localhost", null, 0, null, call_id); 
    110120                        if (status != pjsua.PJ_SUCCESS) { 
    111121                                pj_error_exit("Error making call", status); 
     
    117127                        String userInput; 
    118128                        BufferedReader inBuffReader = new BufferedReader(new InputStreamReader(System.in)); 
     129 
     130                        System.out.println("Press 'h' to hangup all calls, 'q' to quit"); 
     131 
    119132                        try { 
    120133                                userInput = inBuffReader.readLine(); 
     
    124137                        } 
    125138                         
    126                         System.out.println("Press 'h' to hangup all calls, 'q' to quit"); 
    127                          
    128                         if (userInput.equals("q")) 
     139                        if (userInput.equals("q")) { 
    129140                                break; 
    130  
    131                         if (userInput.equals("h")) 
     141                        } else if (userInput.equals("h")) { 
    132142                                pjsua.call_hangup_all(); 
     143                        } else if (userInput.equals("c")) { 
     144                                /* Test string as output param, it is wrapped as string array */ 
     145                                String[] contact = new String[1]; 
     146                                pj_pool_t my_pool = pjsua.pool_create("hello", 256, 256); 
     147                                 
     148                                pjsua.acc_create_uac_contact(my_pool, contact, 0, "sip:localhost"); 
     149                                System.out.println("Test create contact: " + contact[0]); 
     150                                 
     151                                pjsua.pj_pool_release(my_pool); 
     152                        } 
    133153                } 
    134154 
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/my_typemaps.i

    r4549 r4557  
    44%include "typemaps.i" 
    55 
    6 /* Add director typemaps for "int *INOUT" */ 
     6/* Auto destroy JNI object, useful for director */ 
     7%inline %{ 
     8class LocalRefGuard { 
     9    JNIEnv* jenv; 
     10    jobject jobj; 
     11public: 
     12    LocalRefGuard(JNIEnv* jenv_, jobject jobj_) : jenv(jenv_), jobj(jobj_) {} 
     13    ~LocalRefGuard() { if (jobj) jenv->DeleteLocalRef(jobj); } 
     14}; 
     15%} 
     16 
     17/* 
     18 * Add director typemaps for "int *INOUT" 
     19 */ 
    720%typemap(javadirectorin) int *INOUT "$jniinput" 
    821%typemap(directorin, descriptor="[I") int *INOUT %{ 
    922  $input = jenv->NewIntArray(1); 
     23  LocalRefGuard g_$input(jenv, $input); 
    1024  jenv->SetIntArrayRegion($input, 0, 1, (jint*)$1); 
    1125%} 
    1226%typemap(directorout) int *INOUT %{ 
    13   jint* tmp$result = jenv->GetIntArrayElements($input, 0); 
    14   *$result = tmp$result[0]; 
    15   jenv->ReleaseIntArrayElements($input, tmp$result, JNI_ABORT); 
     27  jint tmp$result; 
     28  jenv->GetIntArrayRegion($input, 0, 1, &tmp$result); 
     29  *$result = ($*1_ltype)tmp$result; 
    1630%} 
    1731%typemap(directorargout) int *INOUT %{ 
    18   jint* tmp$1 = jenv->GetIntArrayElements($input, 0); 
    19   *$1 = ($*1_ltype) tmp$1[0]; 
    20   jenv->ReleaseIntArrayElements($input, tmp$1, JNI_ABORT); 
    21 %} 
    22  
    23 /* Add director typemaps for "unsigned *INOUT" */ 
     32  jint tmp$1; 
     33  jenv->GetIntArrayRegion($input, 0, 1, &tmp$1); 
     34  *$1 = ($*1_ltype)tmp$1; 
     35%} 
     36 
     37/* 
     38 * Add director typemaps for "unsigned *INOUT" 
     39 */ 
    2440%typemap(javadirectorin) unsigned *INOUT "$jniinput" 
    2541%typemap(directorin, descriptor="[I") unsigned *INOUT %{ 
    2642  $input = jenv->NewLongArray(1); 
     43  LocalRefGuard g_$input(jenv, $input); 
    2744  jenv->SetLongArrayRegion($input, 0, 1, (jlong*)$1); 
    2845%} 
    2946%typemap(directorout) unsigned *INOUT %{ 
    30   jlong* tmp$result = jenv->GetLongArrayElements($input, 0); 
    31   *$result = tmp$result[0]; 
    32   jenv->ReleaseLongArrayElements($input, tmp$result, JNI_ABORT); 
     47  jlong tmp$result; 
     48  jenv->GetLongArrayRegion($input, 0, 1, &tmp$result); 
     49  *$result = ($*1_ltype)tmp$result; 
    3350%} 
    3451%typemap(directorargout) unsigned *INOUT %{ 
    35   jlong* tmp$1 = jenv->GetLongArrayElements($input, 0); 
    36   *$1 = ($*1_ltype) tmp$1[0]; 
    37   jenv->ReleaseLongArrayElements($input, tmp$1, JNI_ABORT); 
    38 %} 
     52  jlong tmp$1; 
     53  jenv->GetLongArrayRegion($input, 0, 1, &tmp$1); 
     54  *$1 = ($*1_ltype)tmp$1; 
     55%} 
     56 
     57/* 
     58 * Map pj_str_t to java String 
     59 */ 
     60%ignore pj_str_t; 
     61%typemap(jni)             pj_str_t* "jstring" 
     62%typemap(jtype)           pj_str_t* "String" 
     63%typemap(jstype)          pj_str_t* "String" 
     64%typemap(javain)          pj_str_t* "$javainput" 
     65%typemap(javaout)         pj_str_t* { return $jnicall; } 
     66%typemap(javadirectorin)  pj_str_t* "$jniinput" 
     67%typemap(javadirectorout) pj_str_t* "$javacall" 
     68 
     69%typemap(in)              pj_str_t* (pj_str_t str_tmp, char* str_ptr=NULL) %{ 
     70  $1 = &str_tmp; 
     71  if(!$input) pj_strset($1, NULL, 0); 
     72  else { 
     73    str_ptr = (char*)jenv->GetStringUTFChars($input, 0); 
     74    pj_size_t str_len = jenv->GetStringUTFLength($input); 
     75    if (!str_ptr || !str_len) pj_strset($1, NULL, 0); 
     76    else pj_strset($1, str_ptr, str_len); 
     77  } 
     78%} 
     79 
     80%typemap(freearg)         pj_str_t* %{ 
     81  if ($input) 
     82    jenv->ReleaseStringUTFChars($input, str_ptr$argnum); 
     83%} 
     84 
     85%typemap(memberin)        pj_str_t %{ 
     86  if ($1.ptr) free($1.ptr); 
     87  if ($input->ptr) { 
     88    $1.ptr = (char*)malloc($input->slen);                               /* <-- will leak! */ 
     89    memcpy($1.ptr, $input->ptr, $input->slen); 
     90    $1.slen = $input->slen; 
     91  } 
     92%} 
     93 
     94%typemap(out)             pj_str_t* %{ 
     95  char *$1_ptr = (char*)malloc($1->slen+1); 
     96  memcpy($1_ptr, $1->ptr, $1->slen); 
     97  $1_ptr[$1->slen] = '\0'; 
     98  $result = jenv->NewStringUTF($1_ptr); 
     99  free($1_ptr); 
     100%} 
     101 
     102%typemap(directorin,descriptor="Ljava/lang/String;") pj_str_t* %{ 
     103  char *$input_ptr = (char*)malloc($1->slen+1); 
     104  memcpy($input_ptr, $1->ptr, $1->slen); 
     105  $input_ptr[$1->slen] = '\0'; 
     106  $input = jenv->NewStringUTF($input_ptr); 
     107  LocalRefGuard g_$input(jenv, $input); 
     108  free($input_ptr); 
     109%} 
     110 
     111/* 
     112 * Map pj_str_t[ANY] to java String[] 
     113 */ 
     114%typemap(jni)     pj_str_t[ANY] "jobjectArray" 
     115%typemap(jtype)   pj_str_t[ANY] "String[]" 
     116%typemap(jstype)  pj_str_t[ANY] "String[]" 
     117%typemap(javain)  pj_str_t[ANY] "$javainput" 
     118%typemap(javaout) pj_str_t[ANY] { return $jnicall; } 
     119%typemap(in)      pj_str_t[ANY] %{ 
     120  int $1_len = jenv->GetArrayLength($input); 
     121  char** $1_tmpstr = new char*[$1_len]; 
     122  jstring* $1_tmp = new jstring[$1_len]; 
     123  $1 = new pj_str_t[$1_len]; 
     124  int $1_ii; 
     125  for ($1_ii = 0; $1_ii<$1_len; $1_ii++) { 
     126    $1_tmp[$1_ii] = (jstring)jenv->GetObjectArrayElement($input, $1_ii); 
     127    if ($1_tmp[$1_ii]) { 
     128      $1[$1_ii].ptr = $1_tmpstr[$1_ii] = (char*)jenv->GetStringUTFChars($1_tmp[$1_ii], 0); 
     129      $1[$1_ii].slen = jenv->GetStringUTFLength($1_tmp[$1_ii]); 
     130    } else { 
     131      pj_strset(&$1[$1_ii], NULL, 0); 
     132    } 
     133    jenv->DeleteLocalRef($1_tmp[$1_ii]); /* is this ok here? */ 
     134  } 
     135%} 
     136 
     137%typemap(freearg) pj_str_t[ANY] %{ 
     138  for ($1_ii=0; $1_ii<$1_len; $1_ii++) 
     139    if ($1_tmp[$1_ii]) jenv->ReleaseStringUTFChars($1_tmp[$1_ii], $1_tmpstr[$1_ii]); 
     140  delete [] $1; 
     141  delete [] $1_tmp; 
     142  delete [] $1_tmpstr; 
     143%} 
     144 
     145/*  
     146 * Handle setter/getter of a struct member with type of 'array of pj_str_t'. 
     147 */ 
     148%define MY_JAVA_MEMBER_ARRAY_OF_STR(CLASS_NAME, NAME, COUNT_NAME) 
     149 
     150%ignore CLASS_NAME::COUNT_NAME; 
     151 
     152%typemap(memberin)      pj_str_t NAME[ANY], pj_str_t NAME[] { 
     153  int i; 
     154  for (i=0; i<arg1->COUNT_NAME; ++i) 
     155    if ($1[i].ptr) free($1[i].ptr); 
     156   
     157  arg1->COUNT_NAME = $input_len; 
     158  for (i=0; i<arg1->COUNT_NAME; ++i) { 
     159    if ($input->ptr) { 
     160      $1[i].ptr = (char*)malloc($input->slen);                          /* <-- will leak! */ 
     161      memcpy($1[i].ptr, $input->ptr, $input->slen); 
     162      $1[i].slen = $input->slen; 
     163    } 
     164  } 
     165} 
     166 
     167%typemap(out)           pj_str_t NAME[ANY] { 
     168  int i; 
     169  jstring temp_string; 
     170  const jclass clazz = jenv->FindClass("java/lang/String"); 
     171 
     172  $result = jenv->NewObjectArray(arg1->COUNT_NAME, clazz, NULL); 
     173  for (i=0; i<arg1->COUNT_NAME; i++) { 
     174    temp_string = jenv->NewStringUTF($1[i].ptr); 
     175    jenv->SetObjectArrayElement($result, i, temp_string); 
     176    jenv->DeleteLocalRef(temp_string); 
     177  } 
     178} 
     179 
     180%enddef 
     181 
     182/* 
     183 * pj_str_t *INOUT, string as input and output param, handled as single element array. 
     184 */ 
     185%apply pj_str_t[ANY] { pj_str_t *INOUT }; 
     186 
     187%typemap(argout) pj_str_t *INOUT { 
     188  char *$1_ptr = new char[$1[0].slen+1]; 
     189  memcpy($1_ptr, $1[0].ptr, $1[0].slen); 
     190  $1_ptr[$1[0].slen] = '\0'; 
     191  jstring temp_string = jenv->NewStringUTF($1_ptr); 
     192  jenv->SetObjectArrayElement($input, 0, temp_string); 
     193  delete [] $1_ptr; 
     194} 
     195 
     196%typemap(directorin,descriptor="[Ljava/lang/String;") pj_str_t *INOUT %{ 
     197  jstring tmp_$input; 
     198  $input = jenv->NewObjectArray(1, jenv->FindClass("java/lang/String"), NULL); 
     199  LocalRefGuard g_$input(jenv, $input); 
     200  tmp_$input = jenv->NewStringUTF($1[0].ptr); 
     201  LocalRefGuard g_temp_$input(jenv, tmp_$input); 
     202  jenv->SetObjectArrayElement($input, 0, tmp_$input); 
     203%} 
     204 
     205%typemap(directorargout)  pj_str_t *INOUT { 
     206  if(!$input) pj_strset($1, NULL, 0); 
     207  else { 
     208    str_ptr = (char*)jenv->GetStringUTFChars($input, 0); 
     209    pj_size_t str_len = jenv->GetStringUTFLength($input); 
     210    if (!str_ptr || !str_len) pj_strset($1, NULL, 0); 
     211    else { 
     212      $1->ptr = (char*)malloc(str_len);                                 /* <-- will leak! */ 
     213      memcpy($1->ptr, str_ptr, str_len); 
     214      $1->slen = str_len; 
     215    } 
     216  } 
     217} 
     218 
    39219 
    40220/*  
     
    45225%typemap(jtype)  TYPE **NAME "long" 
    46226%typemap(jstype) TYPE **NAME "TYPE" 
    47 %typemap(in)     TYPE **NAME (TYPE *temp = NULL) { temp = (TYPE*)$input; $1 = &temp; } 
    48 %typemap(argout) TYPE **NAME "$input = (jlong)*$1;"  
     227%typemap(in)     TYPE **NAME (TYPE *temp = NULL) "temp = (TYPE*)$input; $1 = &temp;" 
     228%typemap(argout) TYPE **NAME "$input = (jlong)*$1;" 
    49229%typemap(directorin,descriptor="L$packagepath/TYPE;") TYPE **NAME "$input = (jlong)*$1;" 
    50 %typemap(directorargout) TYPE **NAME " *$1 = (TYPE*)$input; " 
    51 %typemap(javain) TYPE **NAME "TYPE.getCPtr($javainput)" 
    52 %typemap(javadirectorin) TYPE **NAME "($jniinput == 0) ? null : new TYPE($jniinput, false)" 
     230%typemap(directorargout)  TYPE **NAME " *$1 = (TYPE*)$input; " 
     231%typemap(javain)          TYPE **NAME "TYPE.getCPtr($javainput)" 
     232%typemap(javadirectorin)  TYPE **NAME "($jniinput == 0) ? null : new TYPE($jniinput, false)" 
    53233%typemap(javadirectorout) TYPE **NAME "TYPE.getCPtr($javacall)" 
    54234%enddef 
     
    57237/*  
    58238 * Generate setter/getter of a struct member typed of 'array of enum' with variable length. 
    59  * Sample usage, given enum array member in this struct: 
    60  * -- 
    61  *   struct pjsip_tls_setting { 
    62  *     .. 
    63  *     unsigned ciphers_num; 
    64  *     pj_ssl_cipher *ciphers; 
    65  *     .. 
    66  *   }; 
    67  * -- 
    68  * apply: 
    69  *   MY_JAVA_MEMBER_ARRAY_OF_ENUM(pjsip_tls_setting, pj_ssl_cipher, ciphers, ciphers_num) 
    70239 */ 
    71240%define MY_JAVA_MEMBER_ARRAY_OF_ENUM(CLASS_NAME, TYPE, NAME, COUNT_NAME) 
    72241 
    73 %apply ARRAYSOFENUMS[] { TYPE* }; 
    74 %typemap(out) TYPE* %{ $result = SWIG_JavaArrayOutInt(jenv, (int*)$1, arg1->COUNT_NAME); %} 
    75 %ignore CLASS_NAME::NAME; 
    76242%ignore CLASS_NAME::COUNT_NAME; 
    77 %extend CLASS_NAME { 
    78     %rename ("%(lowercamelcase)s") set_##NAME; 
    79     %rename ("%(lowercamelcase)s") get_##NAME; 
    80     void set_##NAME(TYPE *NAME, int num) { 
    81         int i; 
    82         if ($self->NAME) free($self->NAME); 
    83         $self->NAME = (TYPE*)calloc(num, sizeof(TYPE)); 
    84         for (i=0; i<num; ++i) $self->NAME[i] = NAME[i]; 
    85         $self->COUNT_NAME = num; 
    86     } 
    87     TYPE* get_##NAME() { 
    88         return $self->NAME; 
    89     } 
    90     ~CLASS_NAME() { 
    91         if ($self->NAME) free($self->NAME); 
    92     } 
    93 }; 
     243%apply ARRAYSOFENUMS[] { TYPE* NAME }; 
     244 
     245%typemap(in)       TYPE* NAME (jint *jarr) %{ 
     246  int size$1 = jenv->GetArrayLength($input); 
     247  if (!SWIG_JavaArrayInInt(jenv, &jarr, (int **)&$1, $input)) return $null; 
     248%} 
     249 
     250%typemap(memberin) TYPE* NAME %{ 
     251  if ($1) free($1); 
     252  arg1->COUNT_NAME = size$input; 
     253  $1 = (TYPE*)calloc(arg1->COUNT_NAME, sizeof(TYPE));                   /* <-- will leak! */ 
     254  for (size_t i = 0; i < (size_t)arg1->COUNT_NAME; i++) 
     255    $1[i] = $input[i]; 
     256%} 
     257 
     258%typemap(out)      TYPE* NAME %{ 
     259  $result = SWIG_JavaArrayOutInt(jenv, (int*)$1, arg1->COUNT_NAME); 
     260%} 
     261 
     262// Hack for avoiding leak, may not work when another macro defines class destructor too 
     263%extend CLASS_NAME { ~CLASS_NAME() { if ($self->NAME) free($self->NAME); } }; 
    94264 
    95265%enddef 
     
    97267 
    98268/*  
    99  * Handle getter of a struct member with type of 'array of pointer to struct/class'. 
    100  * Currently this is applicable for read-only member. 
     269 * Handle setter/getter of a struct member with type of 'array of pointer to struct/class'. 
    101270 */ 
    102271%define MY_JAVA_MEMBER_ARRAY_OF_POINTER(CLASS_NAME, TYPE, NAME, COUNT_NAME) 
    103272 
    104273%ignore CLASS_NAME::COUNT_NAME; 
    105 %immutable CLASS_NAME::NAME; 
    106 %typemap(jni) TYPE *[ANY] "jlongArray" 
    107 %typemap(jtype) TYPE *[ANY] "long[]" 
    108 %typemap(jstype) TYPE *[ANY] "TYPE[]" 
    109 %typemap(javain) TYPE *[ANY] "TYPE.cArrayUnwrap($javainput)" 
    110 %typemap(javaout) TYPE *[ANY] {return TYPE.cArrayWrap($jnicall, $owner);} 
    111  
    112 // somehow "$result" is not preprocessed in "typemap(ret)", use 'jresult' directly then 
    113 %typemap(ret) TYPE *[ANY] { 
    114   jlong *arr; 
    115   int i; 
    116   jresult = JCALL1(NewLongArray, jenv, arg1->COUNT_NAME); 
    117   if (!jresult) { 
     274%typemap(jni)      TYPE* NAME[ANY] "jlongArray" 
     275%typemap(jtype)    TYPE* NAME[ANY] "long[]" 
     276%typemap(jstype)   TYPE* NAME[ANY] "TYPE[]" 
     277%typemap(javain)   TYPE* NAME[ANY] "TYPE.cArrayUnwrap($javainput)" 
     278%typemap(javaout)  TYPE* NAME[ANY] {return TYPE.cArrayWrap($jnicall, $owner);} 
     279 
     280%typemap(in)       TYPE* NAME[ANY] (jlong *jarr) %{ 
     281  if (!SWIG_JavaArrayInUlong(jenv, &jarr, (unsigned long**)&$1, $input)) 
    118282    return $null; 
    119   } 
    120   arr = JCALL2(GetLongArrayElements, jenv, jresult, 0); 
    121   if (!arr) { 
    122     return $null; 
    123   } 
    124   for (i=0; i<arg1->COUNT_NAME; i++) { 
    125     arr[i] = 0; 
    126     *($1_ltype)&arr[i] = $1[i]; 
    127   } 
    128   JCALL3(ReleaseLongArrayElements, jenv, jresult, arr, 0); 
    129 } 
     283  arg1->COUNT_NAME = jenv->GetArrayLength($input); 
     284%} 
     285 
     286%typemap(freearg)  TYPE* NAME[ANY] %{ if ($1) delete [] $1; %} 
     287 
     288%typemap(memberin) TYPE* NAME[ANY] %{ 
     289  for (size_t i = 0; i < (size_t)arg1->COUNT_NAME; i++) $1[i] = $input[i]; 
     290%} 
     291 
     292%typemap(out)      TYPE* NAME[ANY] %{ 
     293  $result = SWIG_JavaArrayOutUlong(jenv, (unsigned long*)$1, arg1->COUNT_NAME); 
     294%} 
    130295 
    131296%typemap(javacode) TYPE %{ 
    132297  protected static long[] cArrayUnwrap($javaclassname[] arrayWrapper) { 
    133       long[] cArray = new long[arrayWrapper.length]; 
    134       for (int i=0; i<arrayWrapper.length; i++) 
    135         cArray[i] = $javaclassname.getCPtr(arrayWrapper[i]); 
    136       return cArray; 
     298    long[] cArray = new long[arrayWrapper.length]; 
     299    for (int i=0; i<arrayWrapper.length; i++) 
     300      cArray[i] = $javaclassname.getCPtr(arrayWrapper[i]); 
     301    return cArray; 
    137302  } 
    138303  protected static $javaclassname[] cArrayWrap(long[] cArray, boolean cMemoryOwn) { 
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py

    r4549 r4557  
    1515 
    1616# CPP (C preprocessor) settings, CPP is needed by pycparser. 
    17 CPP_PATH    = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp' 
     17CPP_PATH        = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp' 
    1818CPP_CFLAGS   = [ 
    1919        r'-DPJ_AUTOCONF', 
     
    5656        'pjmedia_port', 
    5757        'pjmedia_transport', 
    58         'pjsua_media_transport', 
    59         'pjsua_callback', 
    60         'pjmedia_stream' 
     58        'pjsua_media_transport' 
    6159] 
    6260 
    6361FORCE_EXPORT = [ 
    64         'pjsip_event', 
    65         'pjsip_transaction', 
    66         'pjmedia_sdp_session', 
    67         #'pj_str' # plain export result doesn't work! 
     62        'pj_pool_release' 
    6863] 
    6964 
    7065class MyGen(c_generator.CGenerator): 
    71      
    72     def __init__(self, ast): 
    73         super(MyGen, self).__init__() 
    74         self.ast = ast 
    75         self.nodes = OrderedDict() 
    76         self.deps = list() 
    77         self.deps_pending = list() 
    78         self.deps_frozen = False 
    79  
    80         # Generate nodes map (name -> node instances) 
    81         for ext in self.ast.ext: 
    82             name = self._get_node_name(ext) 
    83             if name and not name.startswith(BASE_PREFIX): 
    84                 continue 
    85          
    86             if name in self.nodes: 
    87                 self.nodes[name].append(ext) 
    88                 # always put typedef later, swig issue 
    89                 if isinstance(self.nodes[name][0], c_ast.Typedef): 
    90                     self.nodes[name].reverse() 
    91             else: 
    92                 self.nodes[name] = [ext] 
    93                  
    94         # Generate dependencies, they are all APIs to be exported 
    95         for name in self.nodes.keys(): 
    96             if (not name) or \ 
    97                ((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \ 
    98                       and self._check_video(name)): 
    99                 self._add_dep(name) 
    100         self.deps_frozen = True 
    101          
    102     # Override visit_IdentifierType() to collect "node name" and generate dependencies 
    103     # from this node's children 
    104     def visit_IdentifierType(self, n): 
    105         if not self.deps_frozen: 
    106             for name in n.names: self._add_dep(name) 
    107         return super(MyGen, self).visit_IdentifierType(n) 
    108  
    109     def _check_video(self, name): 
    110         if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)): 
    111             return False 
    112         return True 
    113      
    114     def _get_node_name(self, node): 
    115         s = getattr(node, 'name', None) 
    116         if s: 
    117             return s 
    118         if isinstance(node, c_ast.FuncDef): 
    119             return self._get_node_name(node.decl) 
    120         ss = getattr(node, 'names', None) 
    121         if ss: 
    122             s = ' '.join(ss) 
    123             return s 
    124         if getattr(node, 'type', None): 
    125             return self._get_node_name(node.type) 
    126         return s 
    127  
    128     # Trace node dependencies by recursively inspecting its children. 
    129     # The node itself and all its children will be listed in 'deps'. 
    130     def _add_dep(self, name): 
    131         if (name and not name.startswith(BASE_PREFIX)) or \ 
    132             name in self.deps or name in self.deps_pending: 
    133             return 
    134              
    135         if name in FORCE_STRUCT_AS_OPAQUE and (not name == 'pjsua_callback'): 
    136             self.deps.append(name) 
    137             return 
    138              
    139         self.deps_pending.append(name) 
    140         for node in self.nodes[name]: 
    141             self.visit(node) 
    142         if not self.deps_pending.pop() == name: 
    143             print 'Error initializing dep!' 
    144             sys.exit(1) 
    145         self.deps.append(name) 
    146          
    147     # Opaque struct is identified by empty struct member declaration. 
    148     def _is_struct_opaque(self, node): 
    149         if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \ 
    150            isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None: 
    151             return True 
    152         elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \ 
    153             node.type.decls == None: 
    154             return True 
    155         return False 
    156  
    157     # Check if the specified struct name is opaque. If it is, declare as zero member and 
    158     # tell SWIG to omit ctor/dtor. 
    159     def _process_opaque_struct(self, name, code): 
    160         opaque = True 
    161         if not (name in FORCE_STRUCT_AS_OPAQUE): 
    162             for n in self.nodes[name]: 
    163                 if not self._is_struct_opaque(n): 
    164                     opaque = False 
    165                     break 
    166         if opaque: 
    167             s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n' 
    168             s += 'struct ' + name + ' {};\n' 
    169             return s 
    170  
    171         # Remove "typedef struct/enum ..." without member decl (optional) 
    172         if name: 
    173             code = code.replace('typedef struct '+name+' '+name+';\n', '', 1) 
    174             code = code.replace('typedef enum '+name+' '+name+';\n', '', 1) 
    175         return code 
    176          
    177     def _gen_pjsua_callback(self): 
    178         # init 
    179         cbclass  = '' 
    180         cbproxy = '' 
    181         cbdef = [] 
    182  
    183         n = self.nodes['pjsua_callback'][0] 
    184         raw_lines = self._print_node(n).splitlines() 
    185         for idx, line in enumerate(raw_lines): 
    186             if idx in [0, 1, len(raw_lines)-1]: continue 
    187             fstrs = [] 
    188             # pointer to function type format 
    189             m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line) 
    190             if m: 
    191                 fstrs = [m.group(1).strip(), m.group(2), m.group(3)] 
    192             else: 
    193                 # typedef'd format 
    194                 m = re.match('\s+(.*)\s+(.*);', line) 
    195                 if (not m) or (not self.nodes.has_key(m.group(1))): 
    196                     cbdef.append('  NULL') 
    197                     continue 
    198                 fstrs = ['', m.group(2), ''] 
    199                 n = self.nodes[m.group(1)][0] 
    200                 raw = self._print_node(n) 
    201                 m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw) 
    202                 if not m: 
    203                     cbdef.append('  NULL') 
    204                     continue 
    205                 fstrs[0] = m.group(1).strip() 
    206                 fstrs[2] = m.group(3) 
    207          
    208             cbclass += '  virtual ' + ' '.join(fstrs) 
    209             if fstrs[0] == 'void': 
    210                 cbclass += ' {}\n' 
    211             elif fstrs[1] == 'on_create_media_transport': 
    212                 cbclass += ' { return base_tp; }\n' 
    213             elif fstrs[1] == 'on_call_redirected': 
    214                 cbclass += ' { return PJSIP_REDIRECT_STOP; }\n' 
    215             else: 
    216                 cbclass += ' { return 0; }\n' 
    217  
    218             cbproxy += 'static ' + ' '.join(fstrs) 
    219             params = re.findall('(\w+)[,\)]', fstrs[2]) 
    220             if fstrs[0] == 'void': 
    221                 cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
    222             else: 
    223                 cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
    224  
    225             cbdef.append('  &' + fstrs[1]) 
    226                  
    227         # trail  
    228          
    229         return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n'] 
    230      
    231     # Generate code from the specified node. 
    232     def _print_node(self, node): 
    233         s = '' 
    234         if isinstance(node, c_ast.FuncDef): 
    235             s = self.visit(node) 
    236         else: 
    237             s = self.visit(node) 
    238             if s: s += ';\n' 
    239         return s 
    240  
    241     def go(self): 
    242         s = '' 
    243         for name in self.deps: 
    244             ss = '' 
    245             for node in self.nodes[name]: 
    246                 ss += self._print_node(node) 
    247             s += self._process_opaque_struct(name, ss) 
    248         return s 
    249          
    250     def write_pjsua_callback(self, outdir): 
    251         cb = self._gen_pjsua_callback() 
    252          
    253         fout = open(outdir+'/callbacks.h', 'w+') 
    254         fin  = open('callbacks.h.template', 'r') 
    255         for line in fin: 
    256             if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0: 
    257                 fout.write(cb[0]) 
    258             else: 
    259                 fout.write(line) 
    260         fin.close() 
    261         fout.close() 
    262  
    263         fout = open(outdir+'/callbacks.c', 'w+') 
    264         fin  = open('callbacks.c.template', 'r') 
    265         for line in fin: 
    266             if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0: 
    267                 fout.write(cb[1]) 
    268             elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0: 
    269                 fout.write(cb[2]) 
    270             else: 
    271                 fout.write(line) 
    272         fin.close() 
    273         fout.close() 
    274  
    275 # MAIN           
     66         
     67        def __init__(self, ast): 
     68                super(MyGen, self).__init__() 
     69                self.ast = ast 
     70                self.nodes = OrderedDict() 
     71                self.deps = list() 
     72                self.deps_pending = list() 
     73                self.deps_frozen = False 
     74 
     75                # Generate nodes map (name -> node instances) 
     76                for ext in self.ast.ext: 
     77                        name = self._get_node_name(ext) 
     78                        if name and not name.startswith(BASE_PREFIX): 
     79                                continue 
     80                 
     81                        if name in self.nodes: 
     82                                self.nodes[name].append(ext) 
     83                                # always put typedef later, swig issue 
     84                                if isinstance(self.nodes[name][0], c_ast.Typedef): 
     85                                        self.nodes[name].reverse() 
     86                        else: 
     87                                self.nodes[name] = [ext] 
     88                                 
     89                # Generate dependencies, they are all APIs to be exported 
     90                for name in self.nodes.keys(): 
     91                        if (not name) or \ 
     92                                ((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \ 
     93                                          and self._check_video(name)): 
     94                                self._add_dep(name) 
     95                self.deps_frozen = True 
     96         
     97        # Override visit_IdentifierType() to collect "node name" and generate dependencies 
     98        # from this node's children 
     99        def visit_IdentifierType(self, n): 
     100                if not self.deps_frozen: 
     101                        for name in n.names: self._add_dep(name) 
     102                return super(MyGen, self).visit_IdentifierType(n) 
     103 
     104        def _check_video(self, name): 
     105                if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)): 
     106                        return False 
     107                return True 
     108         
     109        def _get_node_name(self, node): 
     110                s = getattr(node, 'name', None) 
     111                if s: 
     112                        return s 
     113                if isinstance(node, c_ast.FuncDef): 
     114                        return self._get_node_name(node.decl) 
     115                ss = getattr(node, 'names', None) 
     116                if ss: 
     117                        s = ' '.join(ss) 
     118                        return s 
     119                if getattr(node, 'type', None): 
     120                        return self._get_node_name(node.type) 
     121                return s 
     122 
     123        # Trace node dependencies by recursively inspecting its children. 
     124        # The node itself and all its children will be listed in 'deps'. 
     125        def _add_dep(self, name): 
     126                if (name and not name.startswith(BASE_PREFIX)) or \ 
     127                        name in self.deps or name in self.deps_pending: 
     128                        return 
     129                         
     130                if name in FORCE_STRUCT_AS_OPAQUE: 
     131                        self.deps.append(name) 
     132                        return 
     133                         
     134                self.deps_pending.append(name) 
     135                for node in self.nodes[name]: 
     136                        self.visit(node) 
     137                if not self.deps_pending.pop() == name: 
     138                        print 'Error initializing dep!' 
     139                        sys.exit(1) 
     140                self.deps.append(name) 
     141                 
     142        # Opaque struct is identified by empty struct member declaration. 
     143        def _is_struct_opaque(self, node): 
     144                if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \ 
     145                   isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None: 
     146                        return True 
     147                elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \ 
     148                        node.type.decls == None: 
     149                        return True 
     150                return False 
     151 
     152        # Check if the specified struct name is opaque. If it is, declare as zero member and 
     153        # tell SWIG to omit ctor/dtor. 
     154        def _process_opaque_struct(self, name, code): 
     155                opaque = True 
     156                if not (name in FORCE_STRUCT_AS_OPAQUE): 
     157                        for n in self.nodes[name]: 
     158                                if not self._is_struct_opaque(n): 
     159                                        opaque = False 
     160                                        break 
     161                if opaque: 
     162                        s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n' 
     163                        s += 'struct ' + name + ' {};\n' 
     164                        return s 
     165 
     166                # Remove "typedef struct/enum ..." without member decl (optional) 
     167                if name: 
     168                        code = code.replace('typedef struct '+name+' '+name+';\n', '', 1) 
     169                        code = code.replace('typedef enum '+name+' '+name+';\n', '', 1) 
     170                return code 
     171         
     172        def _gen_pjsua_callback(self): 
     173                # init 
     174                cbclass  = '' 
     175                cbproxy = '' 
     176                cbdef = [] 
     177 
     178                n = self.nodes['pjsua_callback'][0] 
     179                raw_lines = self._print_node(n).splitlines() 
     180                for idx, line in enumerate(raw_lines): 
     181                        if idx in [0, 1, len(raw_lines)-1]: continue 
     182                        fstrs = [] 
     183                        # pointer to function type format 
     184                        m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line) 
     185                        if m: 
     186                                fstrs = [m.group(1).strip(), m.group(2), m.group(3)] 
     187                        else: 
     188                                # typedef'd format 
     189                                m = re.match('\s+(.*)\s+(.*);', line) 
     190                                if (not m) or (not self.nodes.has_key(m.group(1))): 
     191                                        cbdef.append('  NULL') 
     192                                        continue 
     193                                fstrs = ['', m.group(2), ''] 
     194                                n = self.nodes[m.group(1)][0] 
     195                                raw = self._print_node(n) 
     196                                m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw) 
     197                                if not m: 
     198                                        cbdef.append('  NULL') 
     199                                        continue 
     200                                fstrs[0] = m.group(1).strip() 
     201                                fstrs[2] = m.group(3) 
     202                 
     203                        cbclass += '  virtual ' + ' '.join(fstrs) 
     204                        if fstrs[0] == 'void': 
     205                                cbclass += ' {}\n' 
     206                        elif fstrs[1] == 'on_create_media_transport': 
     207                                cbclass += ' { return base_tp; }\n' 
     208                        elif fstrs[1] == 'on_call_redirected': 
     209                                cbclass += ' { return PJSIP_REDIRECT_STOP; }\n' 
     210                        else: 
     211                                cbclass += ' { return 0; }\n' 
     212 
     213                        cbproxy += 'static ' + ' '.join(fstrs) 
     214                        params = re.findall('(\w+)[,\)]', fstrs[2]) 
     215                        if fstrs[0] == 'void': 
     216                                cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
     217                        else: 
     218                                cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
     219 
     220                        cbdef.append('  &' + fstrs[1]) 
     221                                 
     222                # trail  
     223                 
     224                return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n'] 
     225         
     226        # Generate code from the specified node. 
     227        def _print_node(self, node): 
     228                s = '' 
     229                if isinstance(node, c_ast.FuncDef): 
     230                        s = self.visit(node) 
     231                else: 
     232                        s = self.visit(node) 
     233                        if s: s += ';\n' 
     234                return s 
     235 
     236        def go(self): 
     237                s = '' 
     238                for name in self.deps: 
     239                        ss = '' 
     240                        for node in self.nodes[name]: 
     241                                ss += self._print_node(node) 
     242                        s += self._process_opaque_struct(name, ss) 
     243                return s 
     244         
     245        def write_pjsua_callback(self, outdir): 
     246                cb = self._gen_pjsua_callback() 
     247                 
     248                fout = open(outdir+'/callbacks.h', 'w+') 
     249                fin  = open('callbacks.h.template', 'r') 
     250                for line in fin: 
     251                        if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0: 
     252                                fout.write(cb[0]) 
     253                        else: 
     254                                fout.write(line) 
     255                fin.close() 
     256                fout.close() 
     257 
     258                fout = open(outdir+'/callbacks.c', 'w+') 
     259                fin  = open('callbacks.c.template', 'r') 
     260                for line in fin: 
     261                        if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0: 
     262                                fout.write(cb[1]) 
     263                        elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0: 
     264                                fout.write(cb[2]) 
     265                        else: 
     266                                fout.write(line) 
     267                fin.close() 
     268                fout.close() 
     269 
     270# MAIN                   
    276271ast = parse_file(SOURCE_PATH, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS) 
    277272#ast.show(attrnames=True, nodenames=True) 
  • pjproject/branches/projects/jni/pjsip/include/pjsua-lib/pjsua.h

    r4549 r4557  
    37303730 * 
    37313731 * @param pool          Pool to allocate memory for the string. 
    3732  * @param contact       The string where the Contact will be stored. 
     3732 * @param p_contact     The string where the Contact will be stored. 
    37333733 * @param acc_id        Account ID. 
    37343734 * @param uri           Destination URI of the request. 
     
    37373737 */ 
    37383738PJ_DECL(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool, 
    3739                                                    pj_str_t *contact, 
     3739                                                   pj_str_t *p_contact, 
    37403740                                                   pjsua_acc_id acc_id, 
    37413741                                                   const pj_str_t *uri); 
     
    37483748 * 
    37493749 * @param pool          Pool to allocate memory for the string. 
    3750  * @param contact       The string where the Contact will be stored. 
     3750 * @param p_contact     The string where the Contact will be stored. 
    37513751 * @param acc_id        Account ID. 
    37523752 * @param rdata         Incoming request. 
     
    37553755 */ 
    37563756PJ_DECL(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool, 
    3757                                                    pj_str_t *contact, 
     3757                                                   pj_str_t *p_contact, 
    37583758                                                   pjsua_acc_id acc_id, 
    37593759                                                   pjsip_rx_data *rdata ); 
Note: See TracChangeset for help on using the changeset viewer.