简体   繁体   English

如何在自定义函数中使用C ++ Builder OPENARRAY

[英]How to use C++ Builder OPENARRAY in a custom function

I would like to use OPENARRAY (or an alternative, if you have one) to pass multiple placeholder variables into my function. 我想使用OPENARRAY (或另一种方法,如果有的话)将多个占位符变量传递到我的函数中。 I know that it can be used for String::Format in this way: 我知道它可以通过以下方式用于String::Format

UnicodeString Text1 = "abc";
int Num2 = 1;
String::Format("Some %s and %d", OPENARRAY(TVarRec, (Text1, Num2));

What I would like is to use Text1 and Text2 variables in something like this: 我想要在这样的情况下使用Text1和Text2变量:

MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2));

Or perhaps: 也许:

MyFunction(OPENARRAY(TVarRec, ("Some %Txt1 and %Num2", "%Txt1", Text1, "%Num2", Num2));

So it would accept the text and replace the placeholder variables with appropriate variable content. 因此它将接受文本并将占位符变量替换为适当的变量内容。

What I don't know is how do I read OPENARRAY parameter content from MyFunction. 我不知道如何从MyFunction中读取OPENARRAY参数内容。

So the function would look like: 因此该函数将如下所示:

UnicodeString MyFunction(UnicodeString Txt, ?WHAT-HERE?)
{
// read openarray here and replace vars
return StringReplace(Txt, ?WHAT-HERE?);
}

So I don't know how do I accept the OPENARRAY variables. 所以我不知道如何接受OPENARRAY变量。 Also, if you have an alternative solution to passing placeholder, variable in similar manner (without the use of C++11), that would also be welcome. 另外,如果您有一种替代方法以类似的方式(不使用C ++ 11)来传递占位符(变量),那也将受到欢迎。

When passing a Delphi-style Open Array to a function, two things are actually passed: 将Delphi样式的Open Array传递给函数时,实际上传递了两件事:

  • a pointer to the first element of the array 指向数组第一个元素的指针

  • the index of the last element of the array (NOT the length of the array, as you might expect!). 数组最后一个元素的索引(如您所料,不是数组的长度!)。

So, in your example, you can declare your function like this: 因此,在您的示例中,您可以这样声明函数:

UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)

And then loop through the array using normal pointer arithmetic. 然后使用普通的指针算法遍历数组。

TVarRec can hold many different data types, so you have to look at its VType field to know what kind of data it is actually referencing, and then access the appropriate data field. TVarRec可以容纳许多不同的数据类型,因此您必须查看其VType字段以了解其实际引用的是哪种数据,然后访问适当的数据字段。 Some values (integers and single characters) are stored directly in the TVarRec itself, while others (strings and other class types) are referenced by pointer instead. 有些值(整数和单个字符)直接存储在TVarRec本身中,而另一些值(字符串和其他类类型)则由指针引用。

For example: 例如:

UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)
{
    if (((Values_High + 1) % 2) != 0)
        throw Exception("uneven number of values!");

    for (int index = 0; index <= Values_High; index += 2)
    {
        String OldValue, NewValue;

        switch (Values[index].VType)
        {
            case vtString:
                OldValue = * static_cast<const ShortString*>(Values[index].VString);
                break;

            case vtPChar:
                OldValue = Values[index].VPChar;
                break;

            case vtPWideChar:
                OldValue = Values[index].VPWideChar;
                break;

            case vtAnsiString:
                OldValue = * static_cast<const AnsiString*>(Values[index].VAnsiString);
                break;

            case vtWideString:
                OldValue = * static_cast<const WideString*>(Values[index].VWideString);
                break;

            case vtUnicodeString:
                OldValue = * static_cast<const UnicodeString*>(Values[index].VUnicodeString);
                break;

            default:
                throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
        }

        switch (Values[index+1].VType)
        {
            case vtInteger:
                NewValue = Values[index+1].VInteger;
                break;

            case vtBoolean:
                NewValue = Values[index+1].VBoolean;
                break;

            case vtChar:
                NewValue = Values[index+1].VChar;
                break;

            case vtExtended:
                NewValue = * static_cast<const Extended*>(Values[index+1].VExtended);
                break;

            case vtString:
                NewValue = * static_cast<const ShortString*>(Values[index+1].VString);
                break;

            case vtPChar:
                NewValue = Values[index+1].VPChar;
                break;

            case vtWideChar:
                NewValue = Values[index+1].VWideChar;
                break;

            case vtPWideChar:
                NewValue = Values[index+1].VPWideChar;
                break;

            case vtAnsiString:
                NewValue = * static_cast<const AnsiString*>(Values[index+1].VAnsiString);
                break;

            case vtCurrency:
                NewValue = * static_cast<const Currency*>(Values[index+1].VCurrency);
                break;

            case vtVariant:
                NewValue = * static_cast<const Variant*>(Values[index+1].VVariant);
                break;

            case vtWideString:
                NewValue = * static_cast<const WideString*>(Values[index+1].VWideString);
                break;

            case vtInt64:
                NewValue = * static_cast<const __int64*>(Values[index+1].VInt64);
                break;

            case vtUnicodeString:
                NewValue = * static_cast<const UnicodeString*>(Values[index+1].VUnicodeString);
                break;

            default:
                throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
        }

        Txt = StringReplace(Txt, OldValue, NewValue, TReplaceFlags() << rfReplaceAll);
    }

    return Txt;
}

MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2)) );

On a side note, when a function takes an open array of TVarRec values, you should use the ARRAYOFCONST() macro instead of the OPENARRAY() macro directly, eg: 附带说明一下,当函数采用TVarRec值的开放数组时,应直接使用ARRAYOFCONST()宏而不是OPENARRAY()宏,例如:

String::Format("Some %s and %d", ARRAYOFCONST(( Text1, Num2 )) );

MyFunction("Some %Txt1 and %Num2", ARRAYOFCONST(( "%Txt1", Text1, "%Num2", Num2 )) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM