Q:

Edit Delphi record from C++ DLL

I'm trying to create a DLL using Visual C++ that is called from a Delphi 5 program. The Delphi program passes in a record, which is then edited in the DLL, and the Delphi program uses the results. 

For example, the Delphi code is similar to the following:
Type dll_btvar = record
    age : smallint;
    name : array[0..11] of char;
    value : Double;
end;

// Import the function from the dll
function foo(CVars : dll_btvar):integer; external 'example.dll';

// Call the dll
function callFoo(var passedVar:dll_btvar):integer;
begin
    result := foo(passedVar);
    // Use passedVar.value
end;

A sample of the C++ code:
In example.h:
#pragma once
#include "dllVar.h"
extern "C" {
    __declspec(dllexport) int foo(DLL_Var var);
}

In example.cpp:
#include "example.h"
int foo(DLL_Var var){
    var.value = var.age + var.name[0];
    return 0;
}

In dllVar.h:
#pragma once
#pragma pack(8)
extern "C" {
    struct DLL_Var {
        short age;
        char name[12];
        double value;
    }
}

I use #pragma pack(8) as that value gave correct alignment so that the passed record is read correctly in the DLL.
In the sample code, when passing an age and name, I expect value to be set by the DLL, which can then be recovered in the Delphi program. Result would be some sort of error code.
Using identical code in C++ Builder 5 did work, however it is of course outdated and I haven't moved all the code in my DLL over (nor do I want to), only the minimum you see here. 
I tested a couple of ways to have Delphi pass an address/pointer to the dll, however they didn't change anything.

Right now, the return value is sent correctly, but the fields of the record (i.e. value) remain unchanged.
What changes do I need to make to either the Delphi or C++ to capture changes in the passed record? I am happy to work extensively with the C++ but I'd prefer to keep the Delphi changes to a minimum since this is old software that I don't want to break.

A:

function foo(CVars : dll_btvar):integer; external 'example.dll';

The problem starts here, in the Delphi code. The record is passed by value. That is, the caller's record variable is copied to a new variable which is then passed to the function. This means that modifications by the callee to this copy of the record are not seen by the caller. You must therefore pass the parameter as a var parameter:
function foo(var CVars : dll_btvar):integer; external 'example.dll';

The next problem is the calling convention. You must use the same calling convention for both sides. Your code uses the default register convention on the Delphi side, which is not supported by non-Borland/Embarcadero tools. Use stdcall or cdecl instead. Let's opt for cdecl, the default for most C++ tools:
function foo(var CVars : dll_btvar):integer; cdecl; external 'example.dll';

To make the C++ code match, pass the argument by reference:
__declspec(dllexport) int __cdecl foo(DLL_Var &var);

Or explicitly use a pointer:
__declspec(dllexport) int __cdecl foo(DLL_Var *var);

In the latter option, the implementation needs to be changed because of the use of a pointer:
int foo(DLL_Var *var){
    var->value = var->age + var->name[0];
    return 0;
}

Using identical code in C++ Builder 5 did work. 

No it did not, because the Delphi code in your question cannot modify the caller's record.

