In principle yes. In practice it ain't quite as simple as you suggest. The complication isn't the function prototype (or even the implementation) anyway, but even there your suggested API is a little simplistic for practical use. The devil is in the error handling. Not only may either the write or the read fail, but either may partially succeed. So, sticking with pseudo-C/C++ where Buffer is a suitable C++ class equivalent to a Perl string, the function prototype changes a little to:
Status TransactI2C(uint8_t address, Buffer wData, uint8_t &written, Bu
+ffer &rBuffer, uint8_t expected);
and the calling code needs to be able to handle statuses like: I2C busy, Write failed, Partial Write, Read Failed, Partial Read, Complete OK.
But the real issue is exactly what the OP is struggling with: simultaneous access. And that isn't solved by just defining a nice API. That has to be solved using some common "process" that serialises access to the I2C port as provided by the OS. That can be non-trivial indeed depending on what the system provides and what your actual use case is. As it happens I've been working to solve exactly those sorts of problems with an embedded system that uses 6 I2C buses, a couple of SPI buses and the odd ADC, USB controller and Ethernet controller thrown in. With all of that stuff running interrupt driven and half of it driving DMA things get pretty interesting!
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond