2017-08-15 149 views
1

我創建了一個簡單的SO例子,演示了將va_list作爲函數arg傳遞的各種方法。我試圖解決的問題是將va_list從共享對象回調到主模塊。將va_list作爲函數參數傳遞

/*libcode.vala shared library (libvala-0.38)*/ 
namespace SOTestLib { 
    public const string TESTSTR = "my test string"; 
    public const string EXPECTFORMATSTR = "expect test:%s"; 
    public const string EXPECTFORMATSTR_VA_ARG0 = "1==1"; 
    public delegate bool delegatefnExpect (bool expression, string format, va_list valist); 
    public delegatefnExpect delfnExpect; 
    public delegate bool delegatefnString (string mystring); 
    public delegatefnString delfnString; 

    public string gTestStr; 
    public string gExpectResultStr; 

    private void show_string(string mystring) { 
     stdout.printf("show_string mystring[%s] gTestStr[%s]\n", mystring, gTestStr); 
     assert (mystring == gTestStr); 
     assert (delfnString != null); 
     delfnString(mystring); 
     } 

    private bool expect(bool expression, string sformat, ...) { 
     assert (delfnExpect != null); 
     assert (sformat == EXPECTFORMATSTR); 

     va_list _valist = va_list(); 
     gExpectResultStr = sformat.vprintf (_valist); 
     stdout.printf("expect[%s]\n", gExpectResultStr); 
     return delfnExpect(expression, sformat , _valist); 
     } 

    private void my_printf (string format, ...) { 
     va_list va_list = va_list(); 
     string res = format.vprintf (va_list); 
     stdout.puts (res); 
     } 
    public int run_demo() { 
     //REFER:https://valadoc.org/glib-2.0/string.vprintf.html 
     // Output: ``Shut up, K-9!`` 
     my_printf ("Shut %s, %c-%d!\n", "up", 'K', 9); 

     gTestStr = TESTSTR; 
     show_string(TESTSTR); 
     expect(1 == 1, EXPECTFORMATSTR, EXPECTFORMATSTR_VA_ARG0); 
     return 0; 
     } 
    } 
/*main.vala linked with libcode.so shared library (libvala-0.38)*/ 
using SOTestLib; 
public bool cbfnString(string test_str) { 
    stdout.printf("cbfnString test_str[%s] gTestStr[%s]\n", test_str, gTestStr); 
    assert (test_str == gTestStr); 
    return true; 
    } 
public bool cbfnExpect(bool expression, string format, va_list args) { 
    stdout.printf("cbfnExpect format[%s] format.length[%d]\n", 
        format, format.length); 
    assert (format == EXPECTFORMATSTR); 
    string res = format.vprintf(args); 
    assert (res != null); 
    stdout.printf("cbfnExpect res[%s] gExpectResultStr[%s]\n", res, gExpectResultStr); 
    assert(res == gExpectResultStr); 
    return expression; 
    } 
static int main(string[] args) { 
    delfnString = (delegatefnString)cbfnString; 
    delfnExpect = (delegatefnExpect)cbfnExpect; 

    return run_demo(); 
    } 

這裏是運行測試的結果...

=========================================================================== 
---Run main -- 
=========================================================================== 
./stackoverflow/libcallback_strings/lib/libcallback_strings.exe 
Shut up, K-9! 
show_string mystring[my test string] gTestStr[my test string] 
cbfnString test_str[my test string] gTestStr[my test string] 
expect[expect test:1==1] 
cbfnExpect format[expect test:%s] format.length[14] 
cbfnExpect res[expect test:(null)] gExpectResultStr[expect test:1==1] 
** 
ERROR:/media/george/SharedData/Projects/Vala/LanguageServer/stackoverflow/libcallback_strings/main.vala:15:cbfnExpect: assertion failed: (res == gExpectResultStr) 
stackoverflow/so_examples.mk:252: recipe for target 'libcallback_strings' failed 
make: *** [libcallback_strings] Aborted 
The terminal process terminated with exit code: 2 

出於某種原因在cbfnExpect,va_list的參數表是不再有效。看起來好像va_list地址(或結構內的地址)只在共享庫中有效。這不正確/允許使用va_list嗎?

回答

0

private bool expect,如果我註釋掉設置gExpectResultStr如下:

//gExpectResultStr = sformat.vprintf (_valist);

然後,在static int main方法的第一行,我添加:

gExpectResultStr = "expect test:1==1";

測試經過。由於每次程序運行時gExpectResultStr都是相同的,所以當程序啓動時我只是將其靜態設置爲正確的值。 正在刪除撥打電話vprintfexpect似乎是修復它。

我的猜測是在C實現中的va_list底下調用sformat.vprintf,導致va_list無效。

當爲生成的C代碼傳遞和失敗的代碼進行比較時,下面是我想到的。盯着代碼一段時間,唯一可能混淆va_list的潛在部分是致電g_strdup_vprintf()。我想這個函數釋放了va_list?

$ diff -Naur libcode-pass.c libcode-fails.c 
--- libcode-pass.c 2018-01-20 09:19:24.455838766 -0800 
+++ libcode-fails.c 2018-01-20 09:19:59.631260461 -0800 
@@ -66,26 +66,32 @@ 
    SOTestLibdelegatefnExpect _tmp0_; 
    const gchar* _tmp1_; 
    va_list _valist = {0}; 
- FILE* _tmp2_; 
- const gchar* _tmp3_; 
- SOTestLibdelegatefnExpect _tmp4_; 
- gboolean _tmp5_; 
- const gchar* _tmp6_; 
+ const gchar* _tmp2_; 
+ gchar* _tmp3_; 
+ FILE* _tmp4_; 
+ const gchar* _tmp5_; 
+ SOTestLibdelegatefnExpect _tmp6_; 
    gboolean _tmp7_; 
+ const gchar* _tmp8_; 
+ gboolean _tmp9_; 
    g_return_val_if_fail (sformat != NULL, FALSE); 
    _tmp0_ = so_test_lib_delfnExpect; 
    _vala_assert (_tmp0_ != NULL, "delfnExpect != null"); 
    _tmp1_ = sformat; 
    _vala_assert (g_strcmp0 (_tmp1_, SO_TEST_LIB_EXPECTFORMATSTR) == 0, "sformat == EXPECTFORMATSTR"); 
    va_start (_valist, sformat); 
- _tmp2_ = stdout; 
- _tmp3_ = so_test_lib_gExpectResultStr; 
- fprintf (_tmp2_, "expect[%s]\n", _tmp3_); 
- _tmp4_ = so_test_lib_delfnExpect; 
- _tmp5_ = expression; 
- _tmp6_ = sformat; 
- _tmp7_ = _tmp4_ (_tmp5_, _tmp6_, _valist); 
- result = _tmp7_; 
+ _tmp2_ = sformat; 
+ _tmp3_ = g_strdup_vprintf (_tmp2_, _valist); 
+ _g_free0 (so_test_lib_gExpectResultStr); 
+ so_test_lib_gExpectResultStr = _tmp3_; 
+ _tmp4_ = stdout; 
+ _tmp5_ = so_test_lib_gExpectResultStr; 
+ fprintf (_tmp4_, "expect[%s]\n", _tmp5_); 
+ _tmp6_ = so_test_lib_delfnExpect; 
+ _tmp7_ = expression; 
+ _tmp8_ = sformat; 
+ _tmp9_ = _tmp6_ (_tmp7_, _tmp8_, _valist); 
+ result = _tmp9_; 
    va_end (_valist); 
    return result; 
}