No, you can't just use some alternate method to transfer the same "stuff" that would have gone into the sendmsg call. When you "pass a file descriptor", what you're really transferring is access to the kernel-internal file object.
The cmsg structure is just a way of formatting a request to the kernel, in which you say "I want to duplicate this open file object, and allow the process that reads this socket to gain access to it". The name SCM_RIGHTS is a clue that what you're transferring is in essence a permission.
Since the request is for manipulation of a kernel-internal object with security implications, you can't sneak around it. You have to make a syscall. And sendmsg is it. (There have been other fd-passing APIs... something with Streams on SysV I think. I don't know if that one is still alive in any recent OSes. For BSD and Linux at least, sendmsg with SCM_RIGHTS is the way to go.)
In general, this is exactly the difference between msg and cmsg: cmsg is used for operations where the kernel is doing more than just copying some bytes from one end of the socket to the other.