When the called contract doesn't adhere to the ABI, we can't just use ContractAInstance.f(); or ContractA ContractAInstance = ContractA(0x123456) to define a new instance.
In this case, we have to use the special low-level call function, using the following call structure:
contract_address.call(bytes4(sha3("function_name(arguments types)")), parameters_values)
In the previous example, we could call f() with two arguments using ContractAaddress.call(bytes4(keccak256("f(uint256,string)")), 10, ”hello”);.
This is a sort of tedious manual construction of the ABI function signature. However, things are getting better with newer Solidity. Since release 0.4.22, the abi.encode(), abi.encodePacked(), abi.encodeWithSelector() ...