killercode
killercode

Reputation: 1706

Faster Parameter Passing in Delphi/C

i have 2 parts application, Delphi and C, and i have 2 questions 1. what is the fastest way to pass parameters to Delphi?

procedure name(Data: string); // Data is Copied to another location before passing so its slow
procedure name(var Data: string); // Data is Passed by pointer, Faster
procedure name(const Data: string); // unknown
  1. i wanna pass parameters by pointers in c, i have a char array and a function, i don't wanna pass the whole array, cut a first part of it and pass the rest

    void testfunction(char **Data)
    {
        printf("Data = %d\n", *Data);
        return;
    }
    
    int main()
    {
        char Data[] = "TEST FUNCTION";
        testfunction(&&Data[4]);        // Error
        return 0;
    }
    

thanks

Upvotes: 3

Views: 838

Answers (4)

Arnaud Bouchez
Arnaud Bouchez

Reputation: 43053

No one did emphasize on the well-known fact that since Delphi 2009, string = UnicodeString so will be exported as PWideChar / LPCWSTR and not PChar / LPCSTR. Worth noting IMHO, because it may be confusing if it is not clear enough in your mind, and expect your code to work with all version of Delphi.

If you want to modify the string content from C library, you should perhaps use a WideString Delphi type instead of a string. WideString is allocated and handled by Windows (this is the COM / Ole string), so you have all the corresponding C API at hand to handle those OLESTR pointers. And this WideString do not suffer from the Delphi 2009 Unicode break (it has always been Unicode).

Of course, WideString is slower than string (for several reasons, the main one is the much slower heap allocation for WideString - getting better since Vista), but it's IMHO a safe a cross-language way of exporting some TEXT data to and from a Delphi application and library (in the Windows world). For instance, the .Net world will like marshaling those OLESTR kind of variable.

Upvotes: 3

long404
long404

Reputation: 1035

The code is a bit misleading I guess. Does it intend to print just " FUNCTION"? If so:

void testfunction(const char *Data)
{
    printf("Data = %s\n", Data);
    return;
}

int main()
{
    char Data[] = "TEST FUNCTION";
    testfunction(Data+4);
    return 0;
}

That will pass the string to that function from index 4 (including) in the array to the rest of it. By passing char* you are not copying the string in that function's local stack. Just the pointer to the beginning of that memory.

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 613412

Delphi strings reside on the heap and are always passed by pointer. Your first example of pass by value is incorrect. Strings passed by value are not copied. Only the reference is copied. This is possible for strings because they have magic copy-on-write behaviour. A dynamic array passed by value is copied.

Using const when passing a string has the best performance because the compiler can optimise out reference counting code.

Your C code is somewhat confused. You don't want char**, rather you want char*. Remember that a C string, a char*, is just a pointer to a null-terminated block of memory. You don't need to take a pointer to a C string since it is already a pointer.

And you mean %s rather than %d surely. To pass a C string starting at the 5th character write Data+4.

 void testfunction(char *Data) {
     printf("Data = %s\n", Data);
 }

int main() {
    char Data[] = "TEST FUNCTION";
    testfunction(Data+4);
    return 0;
}

Upvotes: 6

C Johnson
C Johnson

Reputation: 131

I can only answer the delphi part (my C is a little rusty just now and C pointer/array references make my head hurt when I am current and up to date)

Strings are pointer and are ALWAYS passed by reference, so the data is not copied on passing -EVER.

However, in the case of the

procedure test(s:String);

The pointer S is passed, and if you modify S inside the procedure test, a unique string is generated, and new pointer assigned to S, but not the original passed variable. You can pass string litterals and string expressions/modified on the fly (s+'bla bla bla')

procedure test(var s: String);

the address to the pointer S is passed,

The pointer S is passed, and if you modify S inside the procedure test, a unique string is generated (if required), and new pointer assigned to S, AND the original passed variable. You can NEVER pass string litterals and string expressions/modified on the fly (s+'bla bla bla')

procedure test(const s: string);

The pointer S is passed, and you can not modify S inside the procedure test period. (ok, you can screw around and fool the compiler but it is ugly and hard to do and usually requires a lot of type casting)

Upvotes: 1

Related Questions