Is there a way to get the location of the starting position of a curve? ORIGINAL PROBLEM:
I have this scene with three objects in it: a curve, an arrayed object that follows the curve, and an empty that serves as the offset object of the array. The empty is parented to the curve, and the curve is parented to the object.



I also have this script:

import bpy
from mathutils import Matrix

obj = bpy.context.object
parent = obj.parent

mat = obj.matrix_world.copy()
obj.parent = None
obj.matrix_world = mat
obj.parent = parent
obj.matrix_parent_inverse = parent.matrix_world.inverted()


When I run the script with the curve selected, it doesn't move, which is exactly what I wanted, but when I do it with the empty, it changes its position. Is there something about empty objects that makes this method of changing parents not work? What could I do to keep the empty's position?

EDIT: So I've been trying to figure out what the problem is, and I think the problem is not with the empty, but with the curve. It turns out when I have an empty at the origin (0,0,0) and I parent the empty to the curve via script, the empty gets transported straight to the starting position of the curve, and that's what was causing the offset. Now the question is: Is there a way to get the matrix of the starting point of the curve, so I can maybe use it to bring the empty to the origin/pivot point of the curve object?
Well, I don't know how good of a solution this is, but as suggested by @batFINGER this worked for me.

if parent.type == 'CURVE':
    if parent.data.splines[0].type == 'BEZIER':
        curve = Matrix.Translation(parent.data.splines[0].bezier_points[0].co)
    else:    
        curve = Matrix.Translation(parent.data.splines[0].points[0].co)

    mat = parent.matrix_world @ curve

matdupe = obj.matrix_world.copy()

obj.parent = None
obj.matrix_world = matdupe
obj.parent = parent

if parent.type == 'CURVE':
    obj.matrix_basis = mat.inverted() @ obj.matrix_basis
else:
    obj.matrix_parent_inverse = parent.matrix_world.inverted()